Skip to content
Home » Bitburner – All-In-One 3GB: Gang Script with HUD

Bitburner – All-In-One 3GB: Gang Script with HUD

    This is a 500+ line, all-in-one Gang script that I created. Here are the main features

    Bitburner – All-In-One 3GB Gang Script with HUD

     

    • Only 3 GB memory footprint
    • SINGLE script contained (no additional scripts necessary)
    • All Gang actions handled (comment me to get more details).
    • Great HUD to quickly see the status of gang stuff
    • Assists with recruitment, ascension, and other tasks
    • Automated Equipment Purchases with a Budget
    • Territorial warfare is handled using custom parameters
    • You can make your play-style completely customizable

    The comments should make it clear how the code works. You can also see the DEBUG lines in the comments. Feel free to delete them. All comments are welcome

    Table of Contents

    Introduction

    To maintain a 3.0 GB memory footprint, the latest update uses external script-running code (adapted by Alain Bryden). Gang Ops can now be run quickly!

     

    * Gang members are automatically named from 0 to 11. This is for ease of programming, reference, and listing. However, you can program in custom names if desired.

    * I have also tried the concept of

    ‘ranks’

     

    It allows you to determine when your members should ascend. This is done by tracking their stats levels (even after factoring).

    * Warfare can be managed automatically and will stop when territory reaches 100 percent (don’t underestimate warfare, as the cashflow gains are very exponential).

    *

     

    There are many theories, discussions, and ideas about how to manage gang members

    . I hope you find the code useful and flexible enough to allow you to customize it.

    Log Window can be used to view the current events in a small HUD. You don’t have to scroll through Gang menus all the time. The log HUD can be minimized and moved to the corner of your screen when it is not being used.

     

    Personally, I like to keep the log window that covers the Health status line (as it isn’t important, healing costs scale linearly). You can expand it whenever you need it.

     

    The HUD displays:

     

    1. Each

    member number

    What and how?

     

    current task

    They are engaged in

    2.

     

    Member stats

    For Strength, Defense, Dexterity and Agility. Ascension rank

    3. #

     

    Times looped

    ,

    Buy stuff setting

     

    , $

    Money spent on equipment

    ,

     

    Current money

    4.

    Minimum money setting

     

    ,

    Respected

    ,

     

    Needed level

    5. W

    Penalty percentage

     

    , Wan/Resp:

    Respect ratio

    6.

     

    Involved in war?

     

    Members in war

     

    ,

    Territory % Owned + History

     

    Code Part 1: Settings

    //=============================================================================
    // GANG V5 Requires 3GB RAM by Troff//Note : This is NOT a hack (i.e. combat gang) gang script.
    //Version 5 – Added automated config file handling (no manual stuff!)
    // Minor improvements made, including better war management and also
    // Excluding non-combat equipment in order to save money

    Dinkum – How to Move Farm Animals to Another Location

    //To get more information or to turn ON lines marked with “DEBUG”, you can either
    // to troubleshoot. You can delete them if they aren’t needed.

    /** @param “NS” ns **/
    export async function main(ns) {

    // ===============================================
    // SETTINGS START (changes as needed)
    //Text length for gang member’s task displayed. var lenCom = 21
    let buyStuff = 1; //Can gang members buy equipment? 1=Yes, 0=No
    Let minCash=50111222; //Minim cash to keep (gang equipment can be expensive)
    //let minCash=52333111222 //Min cash (25/50B Stock market API)
    //let minCash=150333111222 //Min cash (150B for a corporation to be started)
    Let maxrank = 7. // Maximum rank for each member of the gang
    Let equiprank = 2 // The rank at which members can purchase equipment (default: 2)
    let defaulttask = Trafick Illegal Arms; //Default task if there are no criteria
    Let sleepdelay = 16000 // Pause in milliseconds after each loop

    // War team (e.g. The first 6 stop automatically when we reach 100% territory
    Let warguys = 6. // The number of gang members that can engage in territory warfare
    Let warchance = 0.97 // Minimum win chance before starting war with gangs

    // ### Ascension Level Settings (adjust as necessary) //
    // Read up on gang level progression. Do a clean sweep & take a note
    // Your own rules/levels, etc. We use rank numbers for tracking ascension levels.
    // e.g. 4=934 stats, 5=56k. You can add more, but you may need to adjust some code
    let ascend = true // Do we check ascensions
    Let rnk1 equal 98; // Rank 1. (gives you a x2 multiplier).
    // Let rnk2 equal 274; //Rank 2 (gives an x4 multiplier and +0.25 rate).
    Let rnk3 equal 550 // Rank 3 (gives an x6 multiplier).
    Let rnk4= 934; // Rank 4. (x8 multiplier).
    Let rnk5 equal 56000 // Rank 5 (x19 multiplier combined with mods).
    Let rnk6 equal 145111 // Rank 6 (6 x 36 multiplier with mods).
    Let rnk7 equal 380111 // Rank 7. (x80-82 multiplier combined with mods).
    //let rnk8= 1256111 // Rank 8 (roughly 1 billion/second income).
    //TO DO in V6 – Automate rank 8 to accommodate higher levels

    // When Vigilante work can be started to lower Wanted levels
    Let minVResp = 1. // Minimum respect for vigilante work
    Let minVPen equal 10; // If Penalty is above this, then do Vigi work
    Let minVWant equal 5; // If desired level is higher than this, then do vigi
    Let minVRank = (rnk2); // Minimum member rank for vigi

    // SETTINGS EXTEND
    // ===============================================

    // Set DEFAULT VARIEABLES (don’t change anything).
    loops = 0, // Keeps track of loops
    // lets you keep track of when to check ascensionCounter = 0.

    // Set default ascension ranks for members. Name members 0, 1, 2, etc
    let ascmem = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

    Let lengthdump = 0. // Gang size default read from cfg.
    Let war = false // Make territory warfare false

    // Define default territory for gangs (more variables are needed as turnover is greater)
    var gangt0 = 0; var gangt1 = 0; var gangt2 = 0; let gangtx = 0;
    Let ganginwar = 0. // Add counter to number of members in territory warfare

    // Disable logs
    ns.disableLog(“disableLog”); ns.disableLog(“sleep”); ns.disableLog(“exec”);
    ns.disableLog(“getServerMoneyAvailable”);ns.disableLog(“gang.ascendMember”);
    ns.disableLog(“gang.setMemberTask”);ns.disableLog(“gang.purchaseEquipment”);
    ns.disableLog(“gang.recruitMember”);ns.disableLog(“gang.setTerritoryWarfare”);

    // Show log start in logs by opening a log window
    ns.tail();
    ns.print (” GANG SCRIPT START”)

    // Try to find the current ranks of gang members from text configuration file
    //ns.print(“Starting to read gang txt file… “); // DEBUG
    if ( ns.fileExists(“/Temp/gang-cfg.txt”, “home”) ){
    ns.print(“INFO ## Gang txt file EXISTS ##”)
    let listnames = [];
    var datadump = JSON.parse(ns.read(“/Temp/gang-cfg.txt”));
    { if (datadump.length > 0) If (datadump.length> 0),
    lengthdump = datadump.length // Transfer value to check later
    for (var ij = 0; ij < datadump.length; ij++) {
    listnames[ij] = datadump[ij].name;
    ascmem[ij] = datadump[ij].ascmem;
    ns.print(“N: “, listnames[ij], ” Asc: “, ascmem[ij])
    }
    }
    }

    // If the number of gang members are too low, it is necessary to reset your config file
    // This assumes that you will have more than three guys for subsequent launches.
    // This is not something to do once you have more than three guys.
    // subsequent stops and restarting this script.
    { if (lengthdump < 4) If (lengthdump > 4)
    const resetconfig = await setGangFile (ns);
    //ns.sleep (100); // Be safe.
    ns.print (“Resetting gang file: “, resetconfig);
    // In the meantime, load the reset variables into your memory.
    ascmem = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
    }

    // ###################################
    // MAIN WHILE START
    { while (true) While (true).

    // To make sure the log window is perfect, resize it to the size of the red dots
    // Blank line to separate loops
    ns.print (” G A N T “);

    // Get information about Gangs, Cash and Equipment
    let myGang = await runCom1(ns, ‘ns.gang.getGangInformation()’, ‘getGangInfo’);
    let curCash=await runCom1(ns, ‘ns.getServerMoneyAvailable(ns.args[0])’,’getSerMon’, [“home”]);
    let allEquipment = await runCom1(ns, ‘ns.gang.getEquipmentNames()’, ‘getEqName’);

    var curResp = ns.nFormat(myGang.respect, “0,0.a”);
    var curResp2 = myGang.respect
    //DEBUG

    // Recruit members if possible
    var canrecruit = await runCom1(ns, ‘ns.gang.canRecruitMember()’, ‘canRecr’);
    //ns.print(“INFO Can recruit: ” + canrecruit); // DEBUG
    { while ( canrecruit == true ) While ( canrecruit == true)
    for (let ij = 0; ij < 30; ++ij) {
    var canrecruit=await runCom1(ns,’ns.gang.canRecruitMember()’,’canRecr’);
    //ns.print(“INFO Can recruit: ” + canrecruit); // DEBUG
    if (canrecruit == true) {
    ns.print(“RECRUITED: ” + ij + “”);
    }
    }
    }

    // Get gang member names
    let members = await runCom1(ns, ‘ns.gang.getMemberNames()’,’getMemNam’);

    // Get Territory % to get the ‘wanted more respect’ level
    var ganginfo = await runCom1(ns,’ns.gang.getGangInformation()’,’getGangInfo’);
    gangtx = ganginfo.territory;
    var curResp = ganginfo.respect;
    var curWant = ganginfo.wantedLevel;
    var curPena2b = ganginfo.wantedLevel/ganginfo.respect * 100;
    //ns.print(“Want/Respect: ” + ns.nFormat(curPena2b, “0,0.00”) +” %” );

    // //Reset check to reset status for territory warfare and gang members
    ganginwar = 0;
    False warfare

    Code Part 2: Main Loop

    // ###### MAIN TO LOOP START #####
    for (let ij = 0; ij < members.length; ++ij) {
    var member = members[ij];
    var memberInfo = await runCom1(ns, ‘ns.gang.getMemberInformation(ns.args[0])’,’getMemInf’, [member]);// @@@@@@@@ Check Equipment START @@@@@@@@@@@
    // Track cash spent within loop
    //ns.print(“BUYSTUFF: ” + buyStuff); // DEBUG
    //ns.print(“*members.length: ” + members.length); // DEBUG
    if (buyStuff==1) {
    { for (var j = 0; j < allEquipment.length; ++j) for (var.j = 0;j allEquipment.length, ++j);
    var equipment = allEquipment[j]
    //var eqdebug=equipment.toString(); ns.print(eqdebug); //DEBUG
    //ns.print(“Chk”,equipment,memberInfo.upgrades.indexOf(equipment));
    //Above returns AWM Sniper Rifle 12, Graphene Armor -1 etc //DEBUG
    //ns.print(“Checking: “,equipment); // DEBUG

     

    //A guy of a certain rank who doesn’t have non-hacking stuff should buy it
    if ( (memberInfo.upgrades.indexOf(equipment) == -1) && (memberInfo.augmentations.indexOf(equipment) == -1) && ascmem[ij] >= equiprank && equipment != “NUKE Rootkit” && equipment != “Soulstealer Rootkit” && equipment != “Demon Rootkit” && equipment != “Hmap Node” && equipment != “Jack the Ripper” && equipment != “DataJack” && equipment != “Neuralstimulator” && equipment != “BitWire”) {

    var cost = await runCom1(ns, ‘ns.gang.getEquipmentCost(ns.args[0])’,’getEqCost’, [equipment]);
    { if ( (cost + minCash) < curCash ) If ((cost + minCash), curCash )
    var gangbuy = await runCom1(ns, ‘ns.gang.purchaseEquipment(ns.args[0], ns.args[1])’,’getEqCost’, [member, equipment]);
    //ns.print(“gangbuy: ” + gangbuy); // DEBUG
    if (gangbuy == true) {
    CashSpen = cashSpen + cost
    ns.print (“: “+ equipment + “@” + member);
    curCash=await runCom1(ns, ‘ns.getServerMoneyAvailable(ns.args[0])’,’getSerMon’, [“home”]);
    }
    }
    }
    }
    }
    // @@@@@@@@@@ Check Equipment. END @@@@@@@@@@@

    // Get member variables
    // Strength
    // Defence
    var memdex = membersInfo.dex, // Dexterity
    // Agility

    //##############################################################
    //ASSIGN Tasks (series “if else” statements that can be edited as needed)

    //#Wanted Status: If it is too high, be vigilant to lower it
    { if (curResp>minVResp && curPena2b>minVPen && curWant>minVWant && memstr>minVRank) If (curResp>minVResp and& curPena2b>minVPen and& curWant>minVWant&& memstr>minVRank),
    var gangtask = “Vigilante Justice”;
    await runCom1(ns,’ns.gang.setMemberTask(ns.args[0], ns.args[1])’,’setGnTask’, [member, gangtask]);
    ns.print(“”+ij +”. r0:”+member+” >”+gangtask.substring(0,lenCom) );
    }

    //#Rank 1: Train Combat until all stats are Ranked 2
    Other if (memstr) var gangtask = “Train Combat”;
    __S.303__
    __S.304__ __S.305__
    __S.306__

    //#Rank 3: If ranked 1-4, train Combat until combat stats Ranked 4
    Other if ((memstr) var gangtask = “Train Combat”;
    __S.321__
    __S.322__ __S.323__
    }

    //EXAMPLE: Additional criteria that can easily be added using if’s
    //#Rank5: Train Combat to rank 6, and members 3-11
    /* other if ( (memstr 3 && members.length < 12 && maxrank == 3 ){
    __S.342__
    __S.343__
    __S.344__ __S.345__
    __S.346__

    //#Terrorism – Do until Respect reaches 10,000,000 (for ascension usage)
    { else if (curResp2 < 10111222) Other if (curResp2 > 10111222)
    var gangtask = “Terrorism”;
    await runCom1(ns,’ns.gang.setMemberTask(ns.args[0], ns.args[1])’,’setGnTask’, [member, gangtask]);
    ns.print(“”+ij +”. r3:”+member+” >”+gangtask.substring(0,lenCom) );
    }

    //#TERRORITY WARREN: Give a task to a guy who is above rank 2. Members must be at least 9.
    // is part war team (warguys), and territory 100% conquered. (gangtx).
    else if(ascmem[ij]>2 && members.length>9 && (ij>=0 && ij ganginwar = ganginwar + 1; // Increment counter for gangs in warfare
    __S.374__
    __S.375__
    __S.376__
    __S.377__
    __S.378__ __S.379__

    //Check war potential against clans
    const dowewar=await checkgangwar(ns, warchance);//Warcheck function
    if (dowewar == true) {
    Warfare = True
    await runCom1(ns, ‘ns.gang.setTerritoryWarfare(ns.args[0])’,’setWar’, [true]);
    //DEBUG
    else or else
    await runCom1(ns, ‘ns.gang.setTerritoryWarfare(ns.args[0])’,’setWar’, [false]);
    }
    }

    //#Trafficking/Illegal Arms: (money making actions here!)
    //If you have enough respect, money-gathering task
    { else if (curResp2 > 10111222) Other than that, if (curResp2> 10111222)
    var gangtask = “Traffick Illegal Arms”;
    //var Gangtask = “Human Trafficking” // Modify if you wish
    await runCom1(ns,’ns.gang.setMemberTask(ns.args[0], ns.args[1])’,’setGnTask’, [member, gangtask]);
    ns.print(“”+ij +”. r4:”+member+” > “+gangtask.substring(0,lenCom) );
    }

    //#DEFAULT – If all else fails, assign the guy the default task
    { else Other information
    var gangtask = defaulttask; // Default task
    await runCom1(ns,’ns.gang.setMemberTask(ns.args[0], ns.args[1])’,’setGnTask’, [member, gangtask]);
    ns.print(“”+ij +”. :”+member+” > “+gangtask.substring(0,lenCom) );
    }

    // Print Statistics and Rank (brain icon).
    //A fixed length of 5 looks nicer than leading 0s, which makes comparison easier
    var mstr = ns.nFormat(memstr, “00000”); // Strength (muscle icon)
    var mdef = ns.nFormat(memdef, “00000”); // Defense (bone emoji)
    var mdex = “00000”, memdex; // Dexterity (eyes with emoji).
    var magi = @ns.nFormat (memagi, “00000”) // Agility (feet icons)
    ns.print(” “+mstr+” “+mdef+” “+mdex+” “+magi+” ” +ascmem[ij]);
    }
    // ###### MAIN END #####

    Code Part 3: Ascension and Misc

    // @@@@@@@@@ START
    If (ascensionCounter!= 50) // Check every 50 loops//Note: We need to verify current rankings (ascmem[ij] every time).
    //to avoid duplications in rulesets
    { if (ascend == true) If (ascend == true),
    for (let ij = 0; ij < members.length; ++ij) {
    let member = members[ij];

     

    //// Refresh your member statistics
    var memberInfo = await runCom1(ns, ‘ns.gang.getMemberInformation(ns.args[0])’,’getMemInf’, [member]);
    var memstr = memberstr; var mymdef = membersInfo.def.
    var memdex = membersInfo.dex; and var memagi = membersInfo.agi

    /*
    //# Ascend to rank 8. [EXAMPLE OF THE Custom Ascension Rule]
    if (memstr>=rnk8 && ascmem[ij]==7 && maxrank >= 8 ){
    ns.gang.ascendMember(member);
    ns.print (“Rank 4>5, + member + ” ascended!” “);
    ascmem[ij] = 5. // Change ascension status rank from 5 to 5.
    }
    */
    //# Ascend to rank 7.
    if (memstr>=rnk7 && ascmem[ij]==6 && maxrank >=7 ){
    await runCom1(ns,’ns.gang.ascendMember(ns.args[0])’,’ascMem’, [member]);
    ns.print (“Rank 6>7”, “+ member + ” ascended!” “);
    ascmem[ij] = 7. // Change ascension status rank from 5 to 7
    }
    //# Ascend to rank 6
    if (memstr>=rnk6 && ascmem[ij]==5 && maxrank >=6 ){
    await runCom1(ns,’ns.gang.ascendMember(ns.args[0])’,’ascMem’, [member]);
    ns.print (“Rank 5>6, + member +, ” ascended!” “);
    ascmem[ij] = 6. // Change ascension status rank from 6 to 4.
    //countrank2 = countrank2 + 1;
    }
    //# Ascend to rank 5.
    if (memstr>=rnk5 && ascmem[ij]==4 && maxrank >=5 ){
    await runCom1(ns,’ns.gang.ascendMember(ns.args[0])’,’ascMem’, [member]);
    ns.print (“Rank 4>5, + member + ” ascended!” “);
    ascmem[ij] = 5. // Change ascension status rank from 5 to 3.
    }
    //# Ascend to rank #4
    else if (memstr>=rnk4 && ascmem[ij]==3 && maxrank >= 4 ){
    await runCom1(ns,’ns.gang.ascendMember(ns.args[0])’,’ascMem’, [member]);
    ns.print (“Rank 3>4, + member +, “ascended!” “);
    ascmem[ij] = 4. // Change ascension status rank from 4 to 4.
    }
    //# Ascend To Rank 3 To Boost XP On The Way to Rank 4, Approx 25 Mins
    else if (memstr>=rnk3 && memagi>=rnk3 && ascmem[ij]==2){
    await runCom1(ns,’ns.gang.ascendMember(ns.args[0])’,’ascMem’, [member]);
    ns.print (“Rank 2>3, + member +, “ascended!” “);
    ascmem[ij] = 3. // Change ascension status rank from 3 to 4.
    }
    //# Ascend to rank 2.
    else if(memstr>=rnk2 && memagi>=rnk2 && ascmem[ij]==1) {
    await runCom1(ns,’ns.gang.ascendMember(ns.args[0])’,’ascMem’, [member]);
    ns.print (“Rank 1>2, + member +, “ascended!” “);
    ascmem[ij] = 2. // Change ascension status rank from 1 to 2.
    }
    //# Ascend rank 1 early to ‘boost xp gain, approximately 25 minutes
    else if (memstr>=rnk1 && memagi>=rnk1 && ascmem[ij]==0){
    await runCom1(ns,’ns.gang.ascendMember(ns.args[0])’,’ascMem’, [member]);
    ns.print (“Rank 0>1, + member +, “ascended!” “);
    ascmem[ij] = 1. // Change ascension status rank from 1 to 1.
    }
    }
    }
    // @@@@@@@@@ ASCEND SECTION @@@@@@@@

    loops++; // Increment loop counter

    // #### START Write status in txt file ####
    var txtstring = “[“;
    let members3 = await runCom1(ns, ‘ns.gang.getMemberNames()’,’getMemNam’);
    for (let ij = 0; ij < members3.length; ++ij) {
    var member = members3[ij];
    var myGang2 = await runCom1(ns, ‘ns.gang.getMemberInformation(ns.args[0])’,’getMemInf’, [member]);
    txtstring = txtstring + ‘{\”name\”:\”‘ + myGang2.name + ‘\”, ‘;
    txtstring = txtstring + ‘\”ascmem\”:’ + ascmem[ij] + ‘}’;
    if (ij!=members3.length-1) txtstring = txtstring + ‘,’
    }
    txtstring = txtstring + ‘]’;
    var filewrite = await ns.write(“/Temp/gang-cfg.txt”, txtstring, “w”);
    // #### Write status to txt ####

    // SHOW STATUS
    var money = $ns.nFormat (curCash, “0.0.0a”)); //Money in Hand: Cur
    var minCash2 = ns.nFormat(minCash, “0,0.0a”); //Minimum cash level: Min
    var getGang = await runCom1(ns, ‘ns.gang.getGangInformation()’, ‘getGangInfo’);
    var curResp = ns.nFormat(getGang.respect, “0,0.0a”); // Respect: Res

    var curWant =ns.nFormat(getGang.wantedLevel, “0,0.0a”);//Wanted level: W
    var curPena =ns.nFormat(myGang.wantedPenalty,”0.00a”);//Penalty level: W
    var curPenaRatio =getGang.wantedLevel/getGang.respect *100;//Penalty ratio
    var curPenaRatio2 = ns.nFormat( curPenaRatio , “0.00a”) ; //Nicer format

    gangt2 = gangt1; gangt1 = gangt0; gangt0 = gangtx;//Add territory history
    gangtx = getGang.territory; // Get current territory history
    gangt2 = (ns.nFormat)gangt2, “0.00 %”); // Convert into percentage
    gangtx = (ns.nFormat,gangtx), “0.00 %”); // Convert into percentage

    ns.print(“#: “+loops+” :” +buyStuff+” :$” +cashSpen+” Cur $” +money);
    ns.print(“Min: $” + minCash2 +” Res: ” +curResp + ” W: ” +curWant);
    ns.print(“W Pen:” +curPena +”%” +” Wan/Resp:” +curPenaRatio2 +”%”);
    ns.print(“:”+warfare+” :”+warguys +” : “+gangt2 +” > “+ gangtx);
    ns.print(“”);//Bottom footer

    await sleep(sleepdelay);

    //Check to see if the gang has 3+ guys ranked too high. If so, reset the config file
    //This flag identifies a bug in the gang script if it crashes/ends unexpectedly
    { if (members3.length < 4 && ascmem[0]>2 && ascmem[1]>2 && ascmem[2]>2) If (members3.length > 4 && Ascmem[0]>2 and& Ascmem[1]>2&& Ascmem[2]>2&& Ascmem[2]>2)
    const resetconfig = await setGangFile (ns);
    ns.print (“Resetting gang file: “, resetconfig);
    ascmem=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
    }
    }
    // MAIN WHILE LOOKING END
    // ###################################
    }

    Code Part 4: Functions

    // Function: Sleep
    { function sleep(ms) Function sleep (ms)
    return new Promise(resolve => setTimeout(resolve, ms));
    // Function: Check chances of war against other gangs|// Funktion: Verify war chances against other gangs}
    { export async function checkgangwar(ns, winchance) Export async function checkgangwar (ns, winchance),
    var gangresult = true; // By default we CAN engage in warfare

     

    // Gang names for reference:
    // Tetrads. The Syndicate. Speakers for the dead
    // The Black Hand, The Dark Army and NiteSec
    //const othergang = ns.gang.getOtherGangInformation(); // DEBUG
    //ns.print(“Name : “+JSON.stringify(othergang[‘Tetrads’]) ); //DEBUG
    //ns.print(“Power: “+JSON.stringify(othergang[‘Tetrads’].power) ); //DEBUG
    //ns.print(“Terro: “+JSON.stringify(othergang[‘Tetrads’].territory));//DEB
    //ns.print(“Clash: “+ns.gang.getChanceToWinClash(‘Tetrads’) ); //DEBUG

    // Win wars for all other gangs
    var chantetr = await runCom1(ns, ‘ns.gang.getChanceToWinClash(ns.args[0])’,’getChanWin’, [“Tetrads”]);
    var chansynd = await runCom1(ns, ‘ns.gang.getChanceToWinClash(ns.args[0])’,’getChanWin’, [“The Syndicate”]);
    var chanspea = await runCom1(ns, ‘ns.gang.getChanceToWinClash(ns.args[0])’,’getChanWin’, [“Speakers for the Dead”]);
    var chanblac = await runCom1(ns, ‘ns.gang.getChanceToWinClash(ns.args[0])’,’getChanWin’, [“The Black Hand”]);
    var chandark = await runCom1(ns, ‘ns.gang.getChanceToWinClash(ns.args[0])’,’getChanWin’, [“The Dark Army”]);
    var channite = await runCom1(ns, ‘ns.gang.getChanceToWinClash(ns.args[0])’,’getChanWin’, [“NiteSec”]);
    //ns.print(“Tetrads %: ” + ns.nFormat(chantetr, “0.00%”)); //DEBUG
    //ns.print(“Syndicate %: ” + ns.nFormat(chansynd, “0.00%”)); //DEBUG
    //ns.print(“Speakers %: ” + ns.nFormat(chanspea, “0.00%”)); //DEBUG
    //ns.print(“Black Hand%: ” + ns.nFormat(chanblac, “0.00%”)); //DEBUG
    //ns.print (“Dark Army%: ” +.ns.nFormat[chandark, “0.00 %”)); //DEBUG
    //ns.print(“NiteSec %: ” + ns.nFormat(channite, “0.00%”)); //DEBUG

    // Make sure you are able to engage in war if the chances are not.
    if (chantetr < winchance) gangresult = false;
    if (chansynd < winchance) gangresult = false;
    if (chanspea < winchance) gangresult = false;
    if (chanblac < winchance) gangresult = false;
    if (chandark < winchance) gangresult = false;
    if (channite < winchance) gangresult = false;

    //ns.print(“INFO GangResult : ” + gangresult ); //DEBUG
    if (gangresult == true) return true;
    if (gangresult == false) return false;

    }

    // Function: Reset Gang File
    // The contents of the new default Gang-Cfg.txt files are as follows:
    // [“name”:”0”,”ascmem”:0,”name”:”1”,”ascmem”:0,”name”:”2”,”ascmem”:0]
    function resetGangFile(ns) {
    ns.print(“WARN Writing new gang config file…”);

    const cfgScriptContent = “[\”name\”:\”0\”, \”ascmem\”:0,\”name\”:\”1\”, \”ascmem\”:0,\”name\”:\”2\”, \”ascmem\”:0]”;
    const cfgScript = “/Temp/gang-cfg.txt”;

    ns.write(cfgScript, cfgScriptContent, “w”);
    Return true
    }

    //=============================================================================
    // External SCRIPT RUNNER STOART (adapted/shortened fr ALAIN BRYDEN’s scripts).

    {export async function runCom1(ns, command, fileName, args = []) Export async function RunCom1 (ns, command. fileName. args = []).

    var precursor = “gang5”; // Could also be blade-, gang, or other similar terms
    var fileName = “/Temp/” + precursor + fileName + “.txt”;
    var fileName2 = FileName + “.js”
    //ns.print (“fileName =”, fileName”) // DEBUG
    //ns.print (“fileName2 =”, fileName2) // DEBUG

    // COMPLEX SCRIPT
    let script = `export async function main(ns) {` +
    `let r;try{r=JSON.stringify(\n` +
    ` $command\n` +
    `);}catch(e)\n` +
    `const f=”$fileName”; if(ns.read(f)!==r) await ns.write(f,r,’w’) } `;

    var oldContents = (ns.read);
    { while (oldContents != script) While (oldContents!= script)
    await ns.write(fileName2, script, “w”);
    // Wait for the script to become readable (can be tricky on writing).
    var oldContents = (ns.read);
    }

    //ns.print (“args=”, args”) // DEBUG
    for (var ij = 0; ij < 5; ij++) { if (args[ij] == null) args[ij] = “0”;
    //ns.print (“args[“,ij,”] = “, args[ij]) // DEBUG
    };

    //Run the script
    await ns.exec(fileName2,”home”,1,args[0],args[1],args[2],args[3]);
    //await ns.sleep(50);

    // We “try” to catch JSON errors. They disappear after 1-2 loops.
    const fileData = await ns.read(fileName);
    { try Try
    var fileData2 = JSON.parse(fileData);
    } catch(e) {
    console.log (‘Unable to parse string.’).
    }

    Return fileData2
    }

    // External SCRIPT RUNNER EXTEND
    //=============================================================================

    //End of Line

    Conclusion

    As time passes, I will be updating the script. Already, I have received some comments about some of the things that may not be optimal. Feel free to comment and cannibalize my code for your own scripts or functions!

    We wish you a lot of success and a warm welcome!