r/Bitburner

Greynet - proof-of-concept prototype mod

Greynet - proof-of-concept prototype mod

GREYNET is a game-within-the-game. You take contracts to sabotage distributed systems (a mechanical heart, a traffic grid, a gene-synthesis line) and you break them by writing code.

Each target is a network of nodes. You breach them, recon them, and compromise them. Breaching is an actual coding puzzle. Recon means hunting through node files to work out how the system can be broken, there's no method that just hands you the answer. You'll need to break into nodes, then read the files inside, pay close attention to how the systems interlock and break them. Then you write the routine that drives the system into a defined failure state before the trace catches up with you.

It's built around the way Bitburner already plays: do it by hand first, then automate. There's an ns.greynet API, and the intended endgame is writing a solver that runs a whole contract on its own. There is even a scoring system based on four things that trade off against each other (execution time, trace cleanliness, RAM, lines of code), so there's usually a better version to go back for; I hope you enjoy optimising each of the metrics. If you've played Opus Magnum, this idea comes directly from their Space/Area/Cost optimization challenges..

Attached is a playable prototype of the first shell, an "Operating Theatre" contract where you stop a mechanical heart, you can try the prototype directly in your browser here: https://jshphysics.github.io/greynet-bitburner-mod/

Breach the nodes, read the docs, beat the countermeasures, write regulate(), or use the script command and automate the whole thing.

Fair warning that it's a prototype: the breach puzzle is a placeholder and it's one hand-built contract rather than the full system. But the core loop is there to try. Much more to come in the real thing.

Happy to hear what people think, particularly whether automating it actually feels good, since that's the part the whole design rests on.

https://preview.redd.it/medtpgofd52h1.png?width=1690&format=png&auto=webp&s=3203de8c8e9978bb6a7d180ff27e41cee75646f1

reddit.com
u/DeviousAlpha — 2 days ago

Why does a file on my home server keep getting deleted with scp?

SOLVED: In another part of the script I had a part that renames ".txt" files and then scps them home, which probably caused scp in the snippet below to overwrite my var file on home with nothing. Thanks KlePu!

Somehow a file with a var I need on different darknet servers keeps getting deleted, when I rename the filename in these lines the new filename gets deleted too, how come?

I edited the name only in these lines, so I'm sure this is doing it somehow.

        if (ns.fileExists("var/deeepth.txt", "home") && ns.scp("var/deeepth.txt", ns.getHostname(), "home")) {
          maxDepth = Number(ns.read("var/deeepth.txt"));
        }
reddit.com
u/KaiseerKenopsia — 2 days ago
▲ 3 r/Bitburner+1 crossposts

Logic Question

Hello, i am a bit lost here and wantet to ask for some help.

I did a Prestige to myself in deleting my save state and trying it all by my own without copying something and now i am at a loss at why my variable wouldn work the same as the ns. "funktion?"? Is it cause if i declare a variable it only checks it when it starts the script and doesnt iterate it again, even the variable is called or what am i not understanding?
i am adding on the examples of the working one with the ns. version and the not working one with the call over the veriable. The script just keeps running with the veriable version.

#Trigger: i am dislexic XD no one ever told me coding is math *.*

Oh and greeting to the community! guess i will engage more in the future:))

https://preview.redd.it/uh9as4gw3z1h1.png?width=1831&format=png&auto=webp&s=5ffbfff05fa79767017851d1c5b1ed6ab39886d2

https://preview.redd.it/7xe838674z1h1.png?width=1707&format=png&auto=webp&s=ecc7be1c384a3694ce8ff5c72ba05805e60eae21

reddit.com
u/Mr-Ordinary- — 3 days ago

Corporations - Help

I just started Bitnode 3.1 and it is overwhelming to say the least. I’ve tried following the various guides available from older versions but I always end up with negative profits and negative funds. Are these guides too outdated? The guide in-game is very dense. Could someone simplify the basics of the buy/sell process for me?

reddit.com
u/CarrotDefiant9098 — 6 days ago
▲ 10 r/Bitburner+2 crossposts

Mobile Game inspired by Lain Aesthetics and Bitburner

Hy everyone i am making this game inspired by Lain and by Bitburner, if anyone want to try It at this link you can find both Linux and Android versions. I already planned of publishing It on the stores but First i want to enhance user experience more and make It better before i make It fully public. If anybody is willing to try It and let me know what he thinks of It, i'd be very grateful. Thanks everyone☺️

github.com
u/CmonMazzu — 8 days ago

Did the server connections change with the update?

This could just be me not paying attention it seems like what servers are connected to each other have changed. Did this happen with the newest update or is it always changing? I have a network map built out in obsidian and it's now incorrect. I just want to know if the server connections are going to keep changing.

reddit.com
u/StrangeCat77 — 8 days ago

Curious but afraid

Hey whatsup guys Im super comfortable with tech concepts and computers, but don't have any Javascript experience whatsoever. Should I only start the game when I have a basic grasp, is there some kind of ultra beginner's guide outside the tutorials in the game? Is it possible to get into the game without coding experience?

edit: Thanks for all the wonderful responses everyone, I'm gonna dive right in

reddit.com
u/Zorian_Vale — 9 days ago

I made a terraforming/incremental game where the Python code you write IS the gameplay

Hi all,

I built a game where the Python code you write is the gameplay, and people who've played it keep telling me it scratches a Bitburner itch. I'd love an honest read from this community: does this concept sound like it would land for you?

I created a terraforming game with a deep (and sinister) story behind it, where every device/vehicle/drone/machine has to be automated/scripted to work with the planet, allowing the player to do whatever they want with them.

You do not just click to mine and smelt iron ore. You need to get a vehicle(called Pioneer), install modules to it(programmatically possible to, dynamically load/unload), program the drill module to drill the ore, program the feeders to transfer items to inventory, storage bin, warehouse, wherever you want, and program the smelters/fabricators using the storages. Everything can be fully automated with code and your end goal is to awaken the planet.

Your solar generators don't just work, they have to be adjusted to track the sun's position, via code. Everything can be managed with code, even the actual shop where you buy things with credits earned from Earth contracts.

I have released a FREE demo on Steam here: https://store.steampowered.com/app/868160/Code_Terraform

Discord: https://discord.gg/hUrK2MRn8s (I'd love to help if you are stuck)

I'd love to hear your opinions about it, thanks!

u/RecursivelyYours — 10 days ago

How do I automate accepting Stanek's gift?

I can move myself to Chongqing with a script, but how do I investigate the church to get invited to "Church of the Machine God" with a script?

reddit.com
u/Puzzleheaded_Toe6299 — 8 days ago

update broke corporations

Corporations no longer progress when you tab out of the browser tab for the game, meaning that in order to progress your corporation, you need to sit and watch the game for however long it takes the corporation to progress to where you want it.

Because of this, corporations are now completely useless if you play the game as an actual idle game.

reddit.com
u/DevouringBeast — 12 days ago

Working on a darknet script (very much a work in progress) and I was refactoring everything to use an object to represent a darknet and I started getting game crashes after about ~5 seconds of running the script? Been staring at it for hours and can't figure out why. Maybe something to do with nested async functions? Any help would be appreciated. I hope its not something too obvious...

Its pretty poorly commented, but think most stuff is pretty explanatorily named. Lmk if there are questions.

***Solved! I was being an idiot. Issue was: dnets = dnets.slice(i, 1); i--; in the second for loop of the while(true) loop. I meant to use splice....... and i don't need the =. So that line is just changed to: dnets.splice(i, 1); i--; And it works great! It just ended up stuck in that for loop forever before.

Can test with just a call to:

ns.exec("dnet/darknet.js","darkweb",1,"home");

File:

const dnetFiles = ["dnet/darknet.js",];
const dnetFile = 0;
/**  {NS} ns */
export async function main(ns) {
  ns.disableLog("ALL");
  const parent = ns.args[0];
  var host = new DarkNet(ns, ns.getHostname(), "");
  ns.print("\n---Darknet Processing Begin---" + host.name);
  host.checkFiles();
  var dnets = [];
  while (true) {
    ns.print("Beginning new loop \n");
    host.openCaches();
    //Update the dnets array with new servers
    const servers = ns.dnet.probe();
    for (const server of servers) {
      if (!dnets.some((darknet) => (darknet.name == server))) {
        dnets.push(new DarkNet(ns, server, host.name));
      }
    }
    //Removes no longer connected servers
    for (let i = 0; i < dnets.length; i++) {
      if (!dnets[i].isValid()) {
        dnets = dnets.slice(i, 1); i--;
      }
    }
    //Connects to and handles connected dnet servers
    for (let darknet of dnets) {
      if (darknet.isValid()) {
        await darknet.authenticateServer();
      }
    }
    await ns.dnet.nextMutation();
  }
}


class DarkNet {
  /** u/param {NS} ns */
  constructor(ns, name, host) {
    this.ns = ns;
    this.name = name;
    this.host = host;
    this.password = null;
    this.possible = null;
    this.result = null;
    this.details = this.ns.dnet.getServerAuthDetails(this.name);
    this.isDynamic = this.getPasswordType();
    if (!this.isDynamic) { this.possible = this.getStaticPassword(); }
  }
  async authenticateServer() {
    if (this.isConnected()) { return true; }
    if (this.isDynamic) { this.result = await this.authenticateDynamic(); }
    else { this.result = await this.authenticateStatic(); }
    if (!this.result.success) {
      this.ns.print("Failed to connect to dnet server " + this.name +
        "\nHint: " + this.details.passwordHint + " Data: " + this.details.data +
        "\nFormat: " + this.details.passwordFormat + " Length: " + this.details.passwordLength +
        " Attempted: " + this.possible + "\nIs Valid: " + this.isValid());
      //ns.exit();
    }
    else {
      this.ns.print("Connected Server:" + this.name + " Password:" + this.password);
      this.setupNewServer();
      await this.ns.sleep(10);
    }
    return this.result.success;
  }
  setupNewServer() {
    this.startProcess(dnetFiles[dnetFile], 1, this.host);
  }
  startProcess(file, threads, args) {
    if (!this.ns.scriptRunning(file, this.name)) {
      this.ns.scp(dnetFiles, this.name, "home");
      const id = this.ns.exec(file, this.name, threads, args);
      if (id == 0) { this.ns.print("Failed to exec " + file + " on " + this.name + " from " + this.host); }
      else { this.ns.print("Running " + file + " on " + this.name); }
      return id;
    }
    return 0;
  }
  async authenticateDynamic() {
    await this.ns.sleep(100);
    return { success: false };
  }
  async authenticateStatic() {
    if (this.possible == null) { return { success: false }; }
    for (const password of this.possible) {
      let result = await this.tryAuth(password);
      if (result.success) { return result; }
    }
    return { success: false };
  }
  async tryAuth(password) {
    if (!this.isValid() || password == null) { return { success: false }; }
    let result = await this.ns.dnet.authenticate(this.name, password);
    if (result.success) { this.password = password; }
    return result;
  }
  getDynamicPassword() {
    this.ns.alert("Test!");
    return null;
  }
  getStaticPassword() {
    if (this.details.passwordLength == 0) { return [""]; }
    if (this.details.passwordHint.length <= 0) { return null; }
    if (this.details.modelId == "ZeroLogon") { return ["0"]; }
    const hintSplit = this.details.passwordHint.split(" ");
    if (hintSplit.includes("default") || hintSplit.includes("factory") || hintSplit.includes("never")) {
      return ["0000", "12345", "admin", "password"];
    }
    if (this.details.data == "" && !isNaN(hintSplit.at(-1))) {
      return [hintSplit.at(-1)];
    }
    if (hintSplit.includes("human")) {
      let password = "";
      for (const char of this.details.data) { if (!isNaN(char)) { password += char; } }
      return [password];
    }
    if (hintSplit.includes("made") || hintSplit.includes("sorted") || hintSplit.includes("shuffled") || hintSplit.includes("uses")) {
      const data = this.details.data;
      if (data.length > 3) { ns.alert("Bad Assumption! shuffled " + this.name); return null; }
      return [data, data[0] + data[2] + data[1], data[1] + data[2] + data[0], data[1] + data[0] + data[2], data[2] + data[0] + data[1], data[2] + data[1] + data[0]];
    }
    if (hintSplit.includes("dog")) { return ["fido", "spot", "rover", "max"]; }
    if (hintSplit.includes("value")) {
      const roman = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
      let password = 0;
      for (let i = 0; i < this.details.data.length; i++) {
        if (roman[this.details.data[i]] < roman[this.details.data[i + 1]]) { password -= roman[this.details.data[i]]; }
        else { password += roman[this.details.data[i]]; }
      }
      return [password];
    }
    if (hintSplit.includes("base")) {
      if (hintSplit.at(-1) != "10") { ns.alert("Bad Assumption! base " + this.name); return null; }
      let parseData = this.details.data.split(",");
      return [parseInt(parseData[1], parseData[0])];
    }
    if (hintSplit.includes("between")) {
      let password = [];
      for (let i = Number(hintSplit[hintSplit.length - 3]) + 1; i < Number(hintSplit[hintSplit.length - 1]); i++) { password.push(i); }
      return password;
    }
    if (hintSplit.includes("divisible")) {
      if (hintSplit[hintSplit.length - 2] != "1") { ns.alert("Bad Assumption! divisible"); return null; }
      let password = [];
      for (let i = 1; i < Math.pow(10, this.details.passwordLength); i++) { password.push(i); }
      return password
    }
    return null;
  }
  getPasswordType() {
    return false;
  }
  isValid() {
    this.details = this.ns.dnet.getServerAuthDetails(this.name);
    if (this.details.isOnline && this.details.isConnectedToCurrentServer) { return true; }
    return false;
  }
  isConnected() {
    this.details = this.ns.dnet.getServerAuthDetails(this.name);
    return this.details.hasSession;
  }
  openCaches() {
    const files = this.ns.ls(this.name);
    for (const file of files) {
      const type = file.split(".").at(-1);
      if (type == "cache") {
        let result = this.ns.dnet.openCache(file);
        this.ns.print("\nCache result: " + result.message);
      }
    }
  }
  checkFiles() {
    const files = this.ns.ls(this.name);
    for (const file of files) {
      const type = file.split(".").at(-1);
      if (type == "lit" || type == "txt") {
        this.ns.scp(file, "darkweb");
        //if (this.name != "darkweb") { this.ns.rm(file,this.name); }
      }
      if (type == "exe") {
        this.ns.print("Executable file found: " + file);
      }
    }
  }
}
reddit.com
u/adjectived — 14 days ago