Advertisement
Farbdose

Bitburner MasterFarm

Feb 10th, 2019
1,722
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { weakPerHack, growPerHack } from "utils.ns";
  2. import { Servers } from "servers.ns";
  3.  
  4. export const scriptFiles = [
  5.     "masterFarm.ns",
  6.     "masterFarmWeak.ns",
  7.     "masterFarmGrow.ns",
  8.     "masterFarmHack.ns",
  9.     "utils.ns",
  10.     "useAllRam.ns",
  11.     "servers.ns"
  12. ];
  13.  
  14. class ExtensibleFunction extends Function {
  15.     constructor(f) {
  16.         return Object.setPrototypeOf(f, new.target.prototype);
  17.     }
  18. }
  19.  
  20. export class VirtualNsFunction extends ExtensibleFunction {
  21.     constructor(threads, target, funcName, scriptName) {
  22.         super(() => this.__call__());
  23.  
  24.         this.threads = threads;
  25.         this.target = target;
  26.         this.funcName = funcName;
  27.         this.scriptName = scriptName;
  28.         this.data = [];
  29.         this.pending = 0;
  30.     }
  31.  
  32.     notifyIncomming() {
  33.         this.pending += 1;
  34.     }
  35.  
  36.     add(ns) {
  37.         this.pending = Math.max(0, this.pending - 1);
  38.         this.data.unshift(ns);
  39.     }
  40.  
  41.     kill() {
  42.         while (this.data && this.data.length > 0) {
  43.             nsExchange.zombies.push(this.data.pop().remoteExit());
  44.         }
  45.     }
  46.  
  47.     get isFree() {
  48.         return this.data[0] && !this.data[0].inUse;
  49.     }
  50.  
  51.     get len() {
  52.         return this.data.length + this.pending;
  53.     }
  54.  
  55.     __call__() {
  56.         if (this.isFree) {
  57.             const ns = this.data.shift();
  58.             ns.inUse = true;
  59.             this.data.push(ns);
  60.  
  61.             let str = "";
  62.             if (nsExchange.verbose) {
  63.                 str = this.funcName[0];
  64.                 switch (this.funcName) {
  65.                     case "hack":
  66.                         str = str.padStart(20);
  67.                         break;
  68.                     case "grow":
  69.                         str = str.padStart(22);
  70.                         break;
  71.                     default:
  72.                         str = str.padStart(24);
  73.                 }
  74.  
  75.                 console.log(Date.now(), "start", str.padEnd(50));
  76.             }
  77.  
  78.             ns[this.funcName](this.target).then(() => {
  79.                 ns.inUse = false;
  80.                 this.data.splice(this.data.indexOf(ns), 1)
  81.                 this.data.unshift(ns);
  82.                 nsExchange.verbose && console.log(Date.now(), "hit", ("          " + str).padEnd(42));
  83.             }).catch((e) => {
  84.                 console.error(e);
  85.             });
  86.  
  87.             return true;
  88.         } else {
  89.             return false;
  90.         }
  91.     }
  92.  
  93. }
  94.  
  95. export class VirtualServer {
  96.     constructor(ns, name, target, maxInstances, workerSizes) {
  97.         this.ns = ns;
  98.         this.name = name;
  99.         this.maxInstances = maxInstances;
  100.         this.weak = new VirtualNsFunction(workerSizes.weak, target, "weaken", "masterFarmWeak.ns");
  101.         this.grow = new VirtualNsFunction(workerSizes.grow, target, "grow", "masterFarmGrow.ns");
  102.         this.hack = new VirtualNsFunction(workerSizes.hack, target, "hack", "masterFarmHack.ns");
  103.     }
  104.  
  105.     async spawnWorker(script, s, virtualFunction, i) {
  106.         let res = await this.ns.exec(script, s, virtualFunction.threads, this.name, s, i);
  107.         if (res) {
  108.             virtualFunction.notifyIncomming();
  109.         }
  110.  
  111.         return res;
  112.     }
  113.  
  114.     async addServer(server) {
  115.         this.ns.scp(scriptFiles, server);
  116.  
  117.         let res = true;
  118.         for (var i = 0; res && this.weak.len < this.maxInstances; i++) {
  119.             console.log(this.weak.len, this.grow.len, this.hack.len);
  120.             let action = this.weak;
  121.             if (this.grow.len < action.len) action = this.grow;
  122.             if (this.hack.len < action.len) action = this.hack;
  123.             res = await this.spawnWorker(action.scriptName, server, action, i);
  124.             console.log(res);
  125.         }
  126.     }
  127.  
  128.     kill() {
  129.         this.weak.kill();
  130.         this.grow.kill();
  131.         this.hack.kill();
  132.         nsExchange[this.name] = undefined;
  133.     }
  134. }
  135.  
  136. export function sortNumber(a, b) {
  137.     return a - b;
  138. }
  139.  
  140. export async function main(ns) {
  141.     const type = ns.args[0];
  142.     ns.mainFunc = this;
  143.  
  144.     switch (type) {
  145.         case "-ctrl":
  146.             {
  147.                 setTimeout(() => {
  148.                     const win = parent["window"];
  149.                     win.doc = win["document"];
  150.                     win.w = win;
  151.                     win.nsExchange = win.nsExchange || {};
  152.                 });
  153.  
  154.                 await ns.sleep(100);
  155.  
  156.                 const server = ns.getHostname();
  157.                 const prefix = server.slice(0, -1);
  158.                 const target = ns.args[1];
  159.                 const margin = ns.args[2];
  160.                 const name = ns.args[3] || server;
  161.                 let mainI;
  162.  
  163.                 let busy = false;
  164.                 const actMargin = 1000;
  165.                 const rAct = {
  166.                     weak: [],
  167.                     grow: [],
  168.                     hack: []
  169.                 };
  170.  
  171.                 let c = 0;
  172.                 const tickTime = 500;
  173.                 const wInterval = 4000;
  174.                 const wTime = ns.getWeakenTime(target) * 1000;
  175.                 const gTime = ns.getGrowTime(target) * 1000;
  176.                 const hTime = ns.getHackTime(target) * 1000;
  177.  
  178.  
  179.                 try {
  180.                     if (nsExchange[name]) {
  181.                         return ns.tprint("Controller name '" + name + "' already in use!");
  182.                     }
  183.                     nsExchange.verbose = true;
  184.                     nsExchange.zombies = [];
  185.                     nsExchange.zombies.kill = () => {
  186.                         nsExchange.zombies.forEach(_ns => _ns.remoteExit());
  187.                     };
  188.                     nsExchange.zombies.clear = () => {
  189.                         nsExchange.zombies.forEach(_ns => {
  190.                             try {
  191.                                 _ns.exit();
  192.                             } catch (e) {
  193.                                 nsExchange.zombies.splice(nsExchange.zombies.indexOf(_ns), 1);
  194.                             }
  195.                         });
  196.                     };
  197.  
  198.                     const weakSafety = 1.1;
  199.                     const farmUnits = Math.floor(margin / ns.hackAnalyzePercent(target));
  200.  
  201.                     const vServer = nsExchange[name] = new VirtualServer(ns, name, target,  wTime / wInterval, {
  202.                         weak: farmUnits * Math.max(1, weakPerHack(ns, target, margin)),
  203.                         grow: farmUnits * Math.max(1, growPerHack(ns, target, margin)),
  204.                         hack: farmUnits * Math.max(1, 1)
  205.                     });
  206.  
  207.                     ns.tprint("f: " + farmUnits + "    h: " + vServer.hack.threads + "    g: " + vServer.grow.threads + "    w: " + vServer.weak.threads);
  208.  
  209.                     await vServer.addServer(server);
  210.                     if (ns.serverExists(prefix + "1")) {
  211.                         for (var i = 1; i < 8; i++) {
  212.                             const s = prefix + i;
  213.                             ns.scp(scriptFiles, s);
  214.  
  215.                             await vServer.addServer(s);
  216.                         }
  217.                     }
  218.  
  219.                     ns.tprint("Startup complete!");
  220.                     console.log(vServer);
  221.  
  222.                     ns.tprint("Starting Main Loop...");
  223.  
  224.                     setTimeout(() => {
  225.                         mainI = setInterval(() => {
  226.                             if (busy) {
  227.                                 nsExchange.verbose && console.info("skipping tick...");
  228.                                 return;
  229.                             } else {
  230.                                 busy = true;
  231.                                 var s = Date.now();
  232.  
  233.                                 try {
  234.                                     if (rAct.weak.length + 5 < wTime / wInterval && c % (wInterval / tickTime) === 0) {
  235.                                         if (vServer.weak()) {
  236.                                             rAct.weak.push(s + wTime);
  237.                                             rAct.weak.sort(sortNumber);
  238.                                         }
  239.                                     }
  240.  
  241.                                     s = Date.now();
  242.                                     if (rAct.weak.length > 0) {
  243.                                         const possible = rAct.weak.map(t => t - gTime - s).filter(t => 0 <= t && t <= actMargin);
  244.                                         if (possible.length > 0 && vServer.grow()) {
  245.                                             rAct.weak.shift();
  246.                                             rAct.grow.push(s + gTime);
  247.                                             rAct.grow.sort(sortNumber);
  248.                                         }
  249.                                     }
  250.  
  251.                                     s = Date.now();
  252.                                     if (rAct.grow.length > 0) {
  253.                                         const possible = rAct.grow.map(t => t - hTime - s).filter(t => 0 <= t && t <= actMargin);
  254.                                         if (possible.length > 0 && vServer.hack()) {
  255.                                             rAct.grow.shift();
  256.                                             rAct.hack.push(s + hTime);
  257.                                             rAct.hack.sort(sortNumber);
  258.                                         }
  259.                                     }
  260.  
  261.  
  262.                                     // run gc
  263.                                     s = Date.now();
  264.                                     rAct.weak = rAct.weak.filter(t => t - s > 0);
  265.                                     rAct.grow = rAct.grow.filter(t => t - s > 0);
  266.                                     rAct.hack = rAct.hack.filter(t => t - s > 0)
  267.                                 } finally {
  268.                                     busy = false;
  269.                                 }
  270.  
  271.                                 if (nsExchange.verbose && c % (30000 / tickTime) === 0) {
  272.                                     console.info(
  273.                                         (Math.floor(((rAct.weak[0] || NaN) - s) / 1000) + "").padStart(4),
  274.                                         (Math.floor(((rAct.grow[0] || NaN) - s) / 1000) + "").padStart(4),
  275.                                         (Math.floor(((rAct.hack[0] || NaN) - s) / 1000) + "").padStart(4),
  276.                                         rAct
  277.                                     );
  278.                                 }
  279.                             }
  280.  
  281.                             c = (c + 1) % 1000000;
  282.                         }, tickTime);
  283.                     }, 1000 - Date.now() % 1000 + tickTime - 1);
  284.  
  285.                     ns.disableLog("sleep");
  286.                     while (true) {
  287.                         await ns.sleep(5000);
  288.                     }
  289.                 } catch (e) {
  290.                     console.error(e);
  291.                     throw e;
  292.                 } finally {
  293.                     clearInterval(mainI);
  294.                     if (nsExchange[name]) {
  295.                         nsExchange[name].kill();
  296.                     }
  297.                 }
  298.  
  299.  
  300.                 break;
  301.             }
  302.  
  303.         case "-kill":
  304.             {
  305.                 if (ns.args[1] && nsExchange[ns.args[1]]) {
  306.                     nsExchange[ns.args[1]].kill();
  307.                 }
  308.  
  309.                 await ns.sleep(5000);
  310.                 ns.tprint("Done");this.data.push(ns);
  311.                 break;
  312.             }
  313.  
  314.         case "-add":
  315.             {
  316.                 await nsExchange[ns.args[2]].addServer(ns.args[1]);
  317.                 break;
  318.             }
  319.  
  320.         case "-all":
  321.             {
  322.                 for (var server of new Servers(ns, ns.args[2]).withRoot) {
  323.                     await nsExchange[ns.args[1]].addServer(server);
  324.                 };
  325.                 break;
  326.             }
  327.  
  328.         default:
  329.             {
  330.                 const prefix = type || "Laser-";
  331.                 const target = ns.args[1] || "omega-net";
  332.                 const margin = ns.args[2] || 90;
  333.  
  334.                 ns.scp(scriptFiles, prefix + "1");
  335.                 ns.exec(scriptFiles[0], prefix + "1", 1, "-ctrl", target, margin);
  336.             }
  337.     }
  338. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement