split and refactor various logics. update "README.md".

[?]
Apr 20, 2020, 11:19 PM
RWMZ7DVLOVPLR4FCIAVSABA5OESYUIEQ2OOZUYNPCNFEBYK5627AC

Dependencies

  • [2] TBPAIFWQ fix regression from previous patch.
  • [3] AXS36NH3 fix divide by 0 during growth.
  • [4] RYYLDBTS minor `README.md` change.
  • [5] CJBGAILA add optional `--target` parameter for `main.js`. update `README.md`.
  • [6] EYKBOK3O optimised the scheduling logic by ensuring that cycles start and finish at minimum security of target.
  • [7] 2LU5Y77O fixed optimum percentage to steal calculator.
  • [8] 6MBUKAG6 remove unneeded functions and comments. update readme.
  • [9] 3TYF4BJS target only hackable servers. replace servers continually.
  • [10] BZ6FC2BT add `cp.js`.
  • [11] BCM3TZOS added `killall.js` option to kill only named scripts. fixed `void_server_buy_or_upgrade` regression that prevented it from working when you don't have servers.
  • [12] 4ACCU75N improve and refactor scheduling logic.
  • [13] VMXI7PS4 added action cap. improved scoring system. fixed parts of security and cash predictors. made lshw loopable.
  • [14] VHWFHMNW 2nd attempt to fix percentage to steal
  • [15] 2BKHJI2S init
  • [16] HHZNTFCT remove `-t` flag for `main.js` which conflicted with the same flag for the `run` command.
  • [17] NQ22FUSW add more options to `main.js`. update `README.md`.

Change contents

  • file deletion: lib.js (----------)
    [5.3711246][5.3787989:3788019](),[5.3788019][5.3734883:3734883]()
    const object_get_constants = function(ns) {
    const object_get_bitnode_multipliers = function(ns) {
    // try {
    // return ns.getBitNodeMultipliers();
    // }
    // catch (error) {
    // return {
    // HackingLevelMultiplier: 1,
    // StrengthLevelMultiplier: 1,
    // DefenseLevelMultiplier: 1,
    // DexterityLevelMultiplier: 1,
    // AgilityLevelMultiplier: 1,
    // CharismaLevelMultiplier: 1,
    // ServerGrowthRate: 1,
    // ServerMaxMoney: 1,
    // ServerStartingMoney: 1,
    // ServerStartingSecurity: 1,
    // ServerWeakenRate: 1,
    // HomeComputerRamCost: 1,
    // PurchasedServerCost: 1,
    // PurchasedServerLimit: 1,
    // PurchasedServerMaxRam: 1,
    // CompanyWorkMoney: 1,
    // CrimeMoney: 1,
    // HacknetNodeMoney: 1,
    // ManualHackMoney: 1,
    // ScriptHackMoney: 1,
    // CodingContractMoney: 1,
    // ClassGymExpGain: 1,
    // CompanyWorkExpGain: 1,
    // CrimeExpGain: 1,
    // FactionWorkExpGain: 1,
    // HackExpGain: 1,
    // FactionPassiveRepGain: 1,
    // FactionWorkRepGain: 1,
    // RepToDonateToFaction: 1,
    // AugmentationMoneyCost: 1,
    // AugmentationRepCost: 1,
    // InfiltrationMoney: 1,
    // InfiltrationRep: 1,
    // FourSigmaMarketDataCost: 1,
    // FourSigmaMarketDataApiCost: 1,
    // CorporationValuation: 1,
    // BladeburnerRank: 1,
    // BladeburnerSkillCost: 1,
    // DaedalusAugsRequirement: 1,
    // };
    // }
    return {
    HackingLevelMultiplier: 1,
    StrengthLevelMultiplier: 1,
    DefenseLevelMultiplier: 1,
    DexterityLevelMultiplier: 1,
    AgilityLevelMultiplier: 1,
    CharismaLevelMultiplier: 1,
    ServerGrowthRate: 1,
    ServerMaxMoney: 1,
    ServerStartingMoney: 1,
    ServerStartingSecurity: 1,
    ServerWeakenRate: 1,
    HomeComputerRamCost: 1,
    PurchasedServerCost: 1,
    PurchasedServerLimit: 1,
    PurchasedServerMaxRam: 1,
    CompanyWorkMoney: 1,
    CrimeMoney: 1,
    HacknetNodeMoney: 1,
    ManualHackMoney: 1,
    ScriptHackMoney: 1,
    CodingContractMoney: 1,
    ClassGymExpGain: 1,
    CompanyWorkExpGain: 1,
    CrimeExpGain: 1,
    FactionWorkExpGain: 1,
    HackExpGain: 1,
    FactionPassiveRepGain: 1,
    FactionWorkRepGain: 1,
    RepToDonateToFaction: 1,
    AugmentationMoneyCost: 1,
    AugmentationRepCost: 1,
    InfiltrationMoney: 1,
    InfiltrationRep: 1,
    FourSigmaMarketDataCost: 1,
    FourSigmaMarketDataApiCost: 1,
    CorporationValuation: 1,
    BladeburnerRank: 1,
    BladeburnerSkillCost: 1,
    DaedalusAugsRequirement: 1,
    };
    };
    const object_get_stats = function(ns) {
    // try {
    // return ns.getStats();
    // }
    // catch (error) {
    // return {
    // hacking: ns.getHackingLevel(),
    // strength: 1,
    // defense: 1,
    // dexterity: 1,
    // agility: 1,
    // charisma: 1,
    // intelligence: 1
    // };
    // }
    return {
    hacking: ns.getHackingLevel(),
    strength: 1,
    defense: 1,
    dexterity: 1,
    agility: 1,
    charisma: 1,
    intelligence: 1
    };
    };
    const object_constants = {
    // cost of server per 1 GB of RAM
    BaseCostFor1GBOfRamServer: 55000,
    // maximum amount of purchased servers allowed
    PurchasedServerLimit: 25,
    // minimum ram of purchased servers possible
    integer_server_ram_min: 2,
    // maximum ram of purchased servers possible. 2^20
    PurchasedServerMaxRam: 1048576,
    // filenames and related functions of exploits
    object_exploits: {
    brutessh: {
    file: "BruteSSH.exe",
    function: "brutessh"
    },
    ftpcrack: {
    file: "FTPCrack.exe",
    function: "ftpcrack"
    },
    relaysmtp: {
    file: "relaySMTP.exe",
    function: "relaysmtp"
    },
    httpworm: {
    file: "HTTPWorm.exe",
    function: "httpworm"
    },
    sqlinject: {
    file: "SQLInject.exe",
    function: "sqlinject"
    }
    },
    // factor used in determining the amount security increases by from a grow or hack
    ServerFortifyAmount: 0.002,
    // amount security decreases by from a weaken
    ServerWeakenAmount: 0.05,
    // base percentage cash increases by from a grow
    ServerBaseGrowthRate: 1.03,
    // max percentage cash increases by from a grow (accounts for server security)
    ServerMaxGrowthRate: 1.0035,
    // hacking multipliers
    object_hacking_multipliers: ns.getHackingMultipliers(),
    // bitnode multipliers
    object_bitnode_multipliers: object_get_bitnode_multipliers(ns),
    // player stats
    object_stats: object_get_stats(ns),
    // filenames and ram cost of helper object_scripts
    object_scripts: {
    weaken: {
    file: "weaken.js",
    ram: 1.75 // or ns.getScriptRam(object_get_constants(ns).object_scripts.weaken.file);
    },
    grow: {
    file: "grow.js",
    ram: 1.75 // or ns.getScriptRam(object_get_constants(ns).object_scripts.grow.file);
    },
    hack: {
    file: "hack.js",
    ram: 1.7 // or ns.getScriptRam(object_get_constants(ns).object_scripts.hack.file);
    }
    },
    string_host: "home" // or ns.getHostname()
    };
    return object_constants;
    };
    // returns an array of all servers in the game
    const array_get_servers = function(ns) {
    const string_host = object_get_constants(ns).string_host;
    const array_servers = [string_host];
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers.length; ++integer_indices_0) {
    const array_scan_results = ns.scan(array_servers[integer_indices_0]);
    for (let integer_indices_1 = 0; integer_indices_1 < array_scan_results.length; ++integer_indices_1) {
    if (array_servers.indexOf(array_scan_results[integer_indices_1]) === -1) {
    array_servers.push(array_scan_results[integer_indices_1]);
    }
    }
    }
    return array_servers;
    };
    // returns the total ram of a server
    const integer_get_server_ram_total = function(ns, string_server) {
    return (ns.getServerRam(string_server))[0];
    };
    // returns the used ram of a server
    const float_get_server_ram_used = function(ns, string_server) {
    return (ns.getServerRam(string_server))[1];
    };
    // returns the amount of free ram of a server
    const float_get_server_ram_free = function(ns, string_server) {
    return integer_get_server_ram_total(ns, string_server) - float_get_server_ram_used(ns, string_server);
    };
    // buy/upgrade servers
    // true if all bought servers have ram == PurchasedServerMaxRam
    const boolean_servers_bought_all_max = function(ns) {
    const array_servers_bought = ns.getPurchasedServers();
    if (array_servers_bought.length > 0) {
    let boolean_tripwire = true;
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers_bought.length; ++integer_indices_0) {
    if (integer_get_server_ram_total(ns, array_servers_bought[integer_indices_0]) < object_get_constants(ns).PurchasedServerMaxRam) {
    boolean_tripwire = false;
    }
    }
    return boolean_tripwire;
    }
    };
    // returns bought server with smallest RAM
    const string_get_server_bought_smallest = function(ns) {
    const array_servers_bought = ns.getPurchasedServers();
    if (array_servers_bought.length > 0) {
    let string_server_smallest;
    let integer_size_smallest = object_get_constants(ns).PurchasedServerMaxRam;
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers_bought.length; ++integer_indices_0) {
    let integer_server_ram_total = integer_get_server_ram_total(ns, array_servers_bought[integer_indices_0]);
    if (integer_server_ram_total < integer_size_smallest) {
    string_server_smallest = array_servers_bought[integer_indices_0];
    integer_size_smallest = integer_server_ram_total;
    }
    }
    return string_server_smallest;
    }
    };
    // returns bought server with biggest RAM
    const string_get_server_bought_biggest = function(ns) {
    const array_servers_bought = ns.getPurchasedServers();
    if (array_servers_bought.length > 0) {
    let string_server_biggest;
    let integer_size_biggest = object_get_constants(ns).integer_server_ram_min;
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers_bought.length; ++integer_indices_0) {
    let integer_server_ram_total = integer_get_server_ram_total(ns, array_servers_bought[integer_indices_0]);
    if (integer_server_ram_total > integer_size_biggest) {
    string_server_biggest = array_servers_bought[integer_indices_0];
    integer_size_biggest = integer_server_ram_total;
    }
    }
    return string_server_biggest;
    }
    };
    // return the RAM of the server with the biggest RAM that you can afford
    const integer_get_server_ram_biggest_afforded = function(ns) {
    const object_constants = object_get_constants(ns);
    if (integer_server_ram_biggest_afforded > object_constants.PurchasedServerMaxRam) {
    integer_server_ram_biggest_afforded = object_constants.PurchasedServerMaxRam;
    }
    return integer_server_ram_biggest_afforded;
    };
    const void_server_buy_or_upgrade = function(ns, string_name) {
    }
    // your servers do not all have the maximum ram possible for purchased servers
    // is cash at least equal to the price of the cheapest server bought + the next highest server after that, which is twice the price of the former, thus 3. this check is so that a server with the same ram as before isn't bought.
    }
    }
    };
    // root servers
    // returns an array of all servers that are yet to be rooted
    const array_get_servers_unrooted = function(ns) {
    const array_servers = array_get_servers(ns);
    const array_servers_unrooted = [];
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers.length; ++integer_indices_0) {
    if (!ns.hasRootAccess(array_servers[integer_indices_0])) {
    array_servers_unrooted.push(array_servers[integer_indices_0]);
    }
    }
    return array_servers_unrooted;
    };
    // tries to open ports of server
    const void_open_ports_try = function(ns, string_server_target) {
    const object_exploits = object_get_constants(ns).object_exploits;
    for (const exploit in object_exploits) {
    try {
    eval("ns." + object_exploits[exploit].function + "(\"" + string_server_target + "\")");
    }
    catch (error) {
    }
    }
    };
    // opens ports and nukes any unrooted servers if the player's hacking level is high enough to do so and the appropriate number of object_exploits are present
    const void_open_ports_nuke_try = function(ns) {
    const array_servers_unrooted = array_get_servers_unrooted(ns);
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers_unrooted.length; ++integer_indices_0) {
    const string_server_unrooted = array_servers_unrooted[integer_indices_0];
    void_open_ports_try(ns, string_server_unrooted);
    try {
    ns.nuke(string_server_unrooted);
    } catch (error) {
    }
    }
    };
    // targetting
    // sort an array of servers by their amounts of RAM, from lowest to highest
    const void_sort_by_server_ram = function(ns, array_servers) {
    return array_servers.sort((string_element_0, string_element_1) => (integer_get_server_ram_total(ns, string_element_0) - integer_get_server_ram_total(ns, string_element_1)));
    };
    };
    const void_sort_by_server_scores = function(ns, array_servers) {
    };
    // weaken, grow, hack
    // returns an array of all rooted servers
    const array_get_servers_rooted = function(ns) {
    const array_servers = array_get_servers(ns);
    const array_servers_rooted = [];
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers.length; ++integer_indices_0) {
    if (ns.hasRootAccess(array_servers[integer_indices_0])) {
    array_servers_rooted.push(array_servers[integer_indices_0]);
    }
    }
    return array_servers_rooted;
    };
    // returns integer_threads_required if it's less than or equal to integer_threads_available, otherwise returns integer_threads_available
    const integer_get_corrected_threads = function(ns, integer_threads_required, integer_threads_available) {
    if (integer_threads_required > integer_threads_available) {
    return integer_threads_available;
    }
    else {
    return integer_threads_required;
    }
    };
    // weaken stuff
    // the threads required for weaken to cause string_server_target's security to decrease by float_weaken_amount. adapted from `weaken` in NetscriptFunctions.js and `weaken` in Server.ts
    const integer_get_threads_required_for_weaken = function(ns, float_weaken_amount) {
    const object_constants = object_get_constants(ns);
    return float_weaken_amount * Math.pow(object_constants.ServerWeakenAmount, -1) * Math.pow(object_constants.object_bitnode_multipliers.ServerWeakenRate, -1);
    };
    // returns the threads required for weaken to cause string_server_target's security to reach minimum
    return Math.ceil(integer_get_threads_required_for_weaken(ns, float_server_target_security - ns.getServerMinSecurityLevel(string_server_target)));
    };
    // returns the threads required for weaken to cause string_server_target's security to reach minimum if possible, otherwise, return max threads that string_server_used can provide
    const integer_get_threads_weaken = function(ns, float_server_used_ram_free, string_server_target, float_server_target_security) {
    const integer_threads_available = Math.trunc(float_server_used_ram_free / object_get_constants(ns).object_scripts.weaken.ram);
    return integer_get_corrected_threads(ns, integer_threads_required, integer_threads_available);
    };
    // grow stuff
    // returns the number of threads of `grow` needed to grow `string_server_target` by the percentage `float_growth` when it has security of `float_server_security`. float_growth = How much the server is being grown by, in DECIMAL form (e.g. 1.5 rather than 50). adapted from `numCycleForGrowth` in https://github.com/danielyxie/bitburner/blob/master/src/Server/ServerHelpers.ts
    const integer_get_threads_for_growth = function(ns, string_server_target, float_server_target_security, float_growth) {
    const object_constants = object_get_constants(ns);
    let ajdGrowthRate = 1 + (object_constants.ServerBaseGrowthRate - 1) / float_server_target_security;
    if (ajdGrowthRate > object_constants.ServerMaxGrowthRate) {
    ajdGrowthRate = object_constants.ServerMaxGrowthRate;
    }
    const serverGrowthPercentage = ns.getServerGrowth(string_server_target) / 100;
    const cycles = Math.log(float_growth)/(Math.log(ajdGrowthRate) * object_constants.object_hacking_multipliers.growth * serverGrowthPercentage * object_constants.object_bitnode_multipliers.ServerGrowthRate);
    return Math.ceil(cycles);
    };
    // Inverse function of integer_get_threads_for_growth. Returns the percentage growth in decimal form (e.g., 2 = 100% growth).
    const float_get_growth_from_threads = function(ns, string_server_target, float_server_target_security, integer_threads) {
    const object_constants = object_get_constants(ns);
    let ajdGrowthRate = 1 + (object_constants.ServerBaseGrowthRate - 1) / float_server_target_security;
    if (ajdGrowthRate > object_constants.ServerMaxGrowthRate) {
    ajdGrowthRate = object_constants.ServerMaxGrowthRate;
    }
    const serverGrowthPercentage = ns.getServerGrowth(string_server_target) / 100;
    const float_growth = Math.pow(ajdGrowthRate, integer_threads * object_constants.object_hacking_multipliers.growth * serverGrowthPercentage * object_constants.object_bitnode_multipliers.ServerGrowthRate);
    return float_growth;
    };
    // returns the threads required by grow to grow string_server_target's cash to its maximum when security is at float_server_target_security and current cash is at float_server_target_cash
    return integer_get_threads_for_growth(ns, string_server_target, float_server_target_security, ns.getServerMaxMoney(string_server_target) / float_server_target_cash);
    };
    // returns the threads required by grow to grow string_server_target's cash to its maximum if possible, otherwise, return max threads that string_server_used can provide
    const integer_get_threads_grow = function(ns, float_server_used_ram_free, string_server_target, float_server_target_security, float_server_target_cash) {
    const integer_threads_available = Math.trunc(float_server_used_ram_free / object_get_constants(ns).object_scripts.grow.ram);
    return integer_get_corrected_threads(ns, integer_threads_required, integer_threads_available);
    };
    // hack stuff
    // returns the percentage of the available cash in string_server_target that is stolen when it is hacked when it has float_server_target_security. adapted from calculatePercentMoneyHacked() in https://github.com/danielyxie/bitburner/blob/master/src/Hacking.js . See also `hackDifficulty` in https://github.com/danielyxie/bitburner/blob/master/src/Server.js
    const float_get_percentage_of_cash_from_available_per_hack = function(ns, string_server_target, float_server_target_security) {
    const object_constants = object_get_constants(ns);
    const balanceFactor = 240;
    const difficultyMult = (100 - float_server_target_security) / 100;
    return percentMoneyHacked * object_constants.object_bitnode_multipliers.ScriptHackMoney;
    };
    // returns the threads required to steal "float_percentage_to_steal" of available money in string_server_target
    };
    // returns the threads required to steal "float_percentage_to_steal" of available money in string_server_target if possible, otherwise, return max threads that string_server_used can provide
    const integer_get_threads_hack = function(ns, float_server_used_ram_free, string_server_target, float_server_target_security, float_percentage_to_steal) {
    const integer_threads_available = Math.trunc(float_server_used_ram_free / object_get_constants(ns).object_scripts.hack.ram);
    return integer_get_corrected_threads(ns, integer_threads_required, integer_threads_available);
    };
    // percentage to steal stuff
    // returns the threads required by grow to grow a string_server_target's money back to its original value after stealing float_percentage_to_steal of it, and assuming security is at float_server_target_security
    const integer_get_threads_required_for_cash_grow_after_percentage_stolen = function(ns, string_server_target, float_server_target_security, float_percentage_to_steal) {
    return integer_get_threads_for_growth(ns, string_server_target, float_server_target_security, Math.pow(1 - float_percentage_to_steal, -1));
    };
    }
    else {
    }
    };
    // returns the number of cycles of bisection to be done to reach a certain precision, rounded up to the nearest integer
    return Math.ceil(Math.log(Math.pow(float_precision, -1)) * Math.pow(Math.log(2), -1));
    };
    let float_ceiling = 1;
    let float_floor = 0;
    let float_percentage_to_steal = (float_ceiling + float_floor) * 0.5;
    float_floor = float_percentage_to_steal;
    }
    else {
    float_ceiling = float_percentage_to_steal;
    }
    float_percentage_to_steal = (float_ceiling + float_floor) * 0.5;
    }
    // cap which can be used so not all money is stolen, which can be bad because it's harder to grow from 0 in most cases
    }
    else {
    return float_percentage_to_steal;
    }
    };
    // copies files to all rooted servers
    const void_copy_files_to_string_servers_rooted = function(ns, array_files, string_source) {
    const array_servers_rooted = array_get_servers_rooted(ns);
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers_rooted.length; ++integer_indices_0) {
    for (let integer_indices_1 = 0; integer_indices_1 < array_files.length; ++integer_indices_1) {
    }
    }
    };
    // scheduling
    const array_get_servers_rooted_sorted_by_ram = function(ns) {
    let array_servers_rooted = array_get_servers_rooted(ns);
    void_sort_by_server_ram(ns, array_servers_rooted);
    return array_servers_rooted;
    };
    const array_get_servers_rooted_sorted_by_score = function(ns) {
    let array_servers_rooted = array_get_servers_rooted(ns);
    void_sort_by_server_scores(ns, array_servers_rooted);
    return array_servers_rooted;
    };
    const string_get_server_rooted_hackable_with_score_biggest = function(ns) {
    const array_servers_rooted_sorted_by_score = array_get_servers_rooted_sorted_by_score(ns);
    // iterate through array in reverse
    for (let integer_indices_0 = array_servers_rooted_sorted_by_score.length - 1; integer_indices_0 >= 0; --integer_indices_0) {
    const string_server_target = array_servers_rooted_sorted_by_score[integer_indices_0];
    if (ns.getHackingLevel() >= ns.getServerRequiredHackingLevel(string_server_target)) {
    return string_server_target;
    }
    }
    };
    if (float_server_target_security > ns.getServerMinSecurityLevel(string_server_target)) {
    return "weaken";
    }
    else {
    if (float_server_target_cash < ns.getServerMaxMoney(string_server_target)) {
    return "grow";
    }
    else {
    return "hack";
    }
    }
    };
    if (float_script_ram * integer_threads > float_server_used_ram_free) {
    return false;
    }
    else {
    return true;
    }
    };
    // Returns time it takes to complete a hack on a server, in seconds. Adapted from `calculateHackingTime` in Hacking.js
    const object_constants = object_get_constants(ns);
    const difficultyMult = ns.getServerRequiredHackingLevel(string_server_target) * float_server_target_security;
    const baseDiff = 500;
    const baseSkill = 50;
    const diffFactor = 2.5;
    const intFactor = 0.1;
    var skillFactor = (diffFactor * difficultyMult + baseDiff);
    // tslint:disable-next-line
    skillFactor /= (hack + baseSkill + (intFactor * int));
    const hackTimeMultiplier = 5;
    const hackingTime = hackTimeMultiplier * skillFactor / object_constants.object_hacking_multipliers.speed;
    return hackingTime;
    };
    // Returns time it takes to complete a grow operation on a server, in seconds. Adapted from `calculateGrowTime` in Hacking.js
    const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
    };
    // Returns time it takes to complete a weaken operation on a server, in seconds. Adapted from `calculateHackingTime` in Hacking.js
    const weakenTimeMultiplier = 4; // Relative to hacking time
    };
    const object_constants = object_get_constants(ns);
    const object_scripts = object_constants.object_scripts;
    const float_server_target_security_minimum = ns.getServerMinSecurityLevel(string_server_target);
    const float_server_target_cash_maximum = ns.getServerMaxMoney(string_server_target);
    const float_time_weaken = float_get_time_weaken(ns, string_server_target, ns.getServerSecurityLevel(string_server_target));
    const float_time_grow = float_get_time_grow(ns, string_server_target, ns.getServerSecurityLevel(string_server_target));
    const float_time_hack = float_get_time_hack(ns, string_server_target, ns.getServerSecurityLevel(string_server_target));
    let float_server_target_security_current = ns.getServerSecurityLevel(string_server_target);
    let float_server_target_cash_current = ns.getServerMoneyAvailable(string_server_target);
    let array_schedule = [];
    // assumes weaken takes longest
    const string_server_used = array_servers_rooted_sorted_by_ram[integer_indices_0];
    let float_server_used_ram_free_current = float_get_server_ram_free(ns, string_server_used);
    string_server_used: string_server_used,
    string_server_target: string_server_target,
    float_server_target_security_before: float_server_target_security_current,
    float_server_target_cash_before: float_server_target_cash_current
    };
    case "weaken": {
    break;
    }
    const integer_threads_weaken = integer_get_threads_weaken(ns, float_server_used_ram_free_current, string_server_target, float_server_target_security_current);
    float_server_used_ram_free_current -= integer_threads_weaken * object_scripts.weaken.ram;
    if (float_server_target_security_uncorrected < float_server_target_security_minimum) {
    float_server_target_security_current = float_server_target_security_minimum;
    }
    else {
    float_server_target_security_current = float_server_target_security_uncorrected;
    }
    schedule_item.integer_threads = integer_threads_weaken;
    array_schedule.push(schedule_item);
    break;
    }
    case "grow": {
    break;
    }
    const integer_threads_grow = integer_get_threads_grow(ns, float_server_used_ram_free_current, string_server_target, float_server_target_security_current, float_server_target_cash_current);
    float_server_used_ram_free_current -= integer_threads_grow * object_scripts.grow.ram;
    if (float_server_target_cash_current_uncorrected > float_server_target_cash_maximum) {
    float_server_target_cash_current = float_server_target_cash_maximum;
    }
    else {
    float_server_target_cash_current = float_server_target_cash_current_uncorrected;
    }
    // the following is adapted from `processSingleServerGrowth` in ServerHelpers.ts and `fortify` in Server.ts
    schedule_item.integer_threads = integer_threads_grow;
    array_schedule.push(schedule_item);
    break;
    }
    case "hack": {
    break;
    }
    // the following is adapted from `hack` in NetscriptFunctions.js and `fortify` in Server.ts
    }
    schedule_item.integer_threads = integer_threads_hack;
    array_schedule.push(schedule_item);
    break;
    }
    }
    }
    }
    };
    // script executors
    // execute the "weaken.js" script
    const void_exec_script_weaken = async function(ns, string_server_used, string_server_target, threads, delay, identifier) {
    await ns.exec(object_get_constants(ns).object_scripts.weaken.file, string_server_used, threads, string_server_used, string_server_target, delay, identifier);
    };
    // execute the "grow.js" script
    const void_exec_script_grow = async function(ns, string_server_used, string_server_target, threads, delay, identifier) {
    await ns.exec(object_get_constants(ns).object_scripts.grow.file, string_server_used, threads, string_server_used, string_server_target, delay, identifier);
    };
    // execute the "hack.js" script
    const void_exec_script_hack = async function(ns, string_server_used, string_server_target, threads, delay, identifier) {
    await ns.exec(object_get_constants(ns).object_scripts.hack.file, string_server_used, threads, string_server_used, string_server_target, delay, identifier);
    };
    const object_constants = object_get_constants(ns);
    const object_scripts = object_constants.object_scripts;
    void_server_buy_or_upgrade(ns, string_servers_bought_name);
    // opens ports and nukes any unrooted servers if the player's hacking level is high enough to do so and the appropriate number of object_exploits are present
    void_open_ports_nuke_try(ns);
    // copy object_scripts to rooted servers
    void_copy_files_to_string_servers_rooted(ns, [
    object_scripts.weaken.file,
    object_scripts.grow.file,
    object_scripts.hack.file
    }
    }
    };
    // make and run actual hacking schedule
    const array_schedule = array_make_schedule(ns, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target, string_job_decider);
    await void_schedule_runner(ns, array_schedule);
    return array_schedule[array_schedule.length - 1].integer_time_job_finishes_seconds * 1000;
    ], object_constants.string_host);
    break;
    }
    const array_schedule_prepare = array_make_schedule(ns, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target, string_job_decider_prepare);
    if (array_schedule_prepare.length > 0) {
    await void_schedule_runner(ns, array_schedule_prepare);
    await ns.sleep(array_schedule_prepare[array_schedule_prepare.length - 1].integer_time_job_finishes_seconds * 1000);
    // prepare the target if necessary
    while (true) {
    if (
    ns.getServerSecurityLevel(string_server_target) === ns.getServerMinSecurityLevel(string_server_target) &&
    ns.getServerMoneyAvailable(string_server_target) === ns.getServerMaxMoney(string_server_target)
    ) {
    void_buy_home_ram(ns);
    let string_server_target = string_server_target_argument;
    if (string_server_target_argument === null) {
    string_server_target = string_get_server_rooted_hackable_with_score_biggest(ns);
    }
    // returns the the time it'll take to finish in milliseconds.
    export const void_runner = async function(ns, string_servers_bought_name, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target_argument) {
    const void_schedule_runner = async function(ns, array_schedule) {
    for (let integer_indices_0 = 0; integer_indices_0 < array_schedule.length; ++integer_indices_0) {
    switch (array_schedule[integer_indices_0].string_job) {
    case "weaken": {
    await void_exec_script_weaken(ns, array_schedule[integer_indices_0].string_server_used, array_schedule[integer_indices_0].string_server_target, array_schedule[integer_indices_0].integer_threads, array_schedule[integer_indices_0].float_delay_seconds * 1000, integer_indices_0);
    break;
    }
    case "grow": {
    await void_exec_script_grow(ns, array_schedule[integer_indices_0].string_server_used, array_schedule[integer_indices_0].string_server_target, array_schedule[integer_indices_0].integer_threads, array_schedule[integer_indices_0].float_delay_seconds * 1000, integer_indices_0);
    break;
    }
    case "hack": {
    await void_exec_script_hack(ns, array_schedule[integer_indices_0].string_server_used, array_schedule[integer_indices_0].string_server_target, array_schedule[integer_indices_0].integer_threads, array_schedule[integer_indices_0].float_delay_seconds * 1000, integer_indices_0);
    break;
    }
    }
    }
    };
    // remove schedule items near the end that cause security to not equal minimum. in other words, the target should have minimum security when the cycle finishes. this is to make the next cycle of jobs run as quick as possible. TODO: make it so that we don't have to do this deleting step, instead, the array making steps above should already take into this into account and don't make more items than is needed.
    let boolean_have_not_seen_item_with_security_minimum = true;
    while (boolean_have_not_seen_item_with_security_minimum) {
    break;
    }
    boolean_have_not_seen_item_with_security_minimum = false;
    break;
    }
    else {
    }
    }
    }
    if (boolean_have_not_seen_item_with_security_minimum) {
    return array_schedule;
    }
    else {
    return array_schedule_edited;
    }
    array_schedule_edited.splice(integer_indices_1, 1);
    const object_job = array_schedule_edited[integer_indices_1];
    if (object_job.float_server_target_security_current === float_server_target_security_minimum) {
    for (let integer_indices_1 = array_schedule_edited.length - 1; integer_indices_1 >= 0; --integer_indices_1) {
    if (!boolean_have_not_seen_item_with_security_minimum) {
    let array_schedule_edited = array_schedule;
    ++integer_array_schedule_length;
    schedule_item.integer_time_job_finishes_seconds = integer_time_job_finishes_seconds;
    integer_time_job_finishes_seconds += float_padding_seconds;
    schedule_item.float_delay_seconds = integer_time_job_finishes_seconds - float_time_hack + float_padding_seconds;
    else {
    float_server_target_cash_current = float_server_target_cash_current_uncorrected;
    }
    float_server_target_security_current += float_get_security_increase_from_hack(ns, string_server_target, float_server_target_security_current, float_server_target_cash_before, integer_threads_hack);
    schedule_item.float_server_target_security_current = float_server_target_security_current;
    const float_server_target_cash_before = float_server_target_cash_current;
    const float_server_target_cash_current_uncorrected = float_server_target_cash_current - Math.floor(float_server_target_cash_current * float_get_percentage_of_cash_from_available_per_hack(ns, string_server_target, float_server_target_security_current)) * integer_threads_hack;
    if (float_server_target_cash_current_uncorrected < 0) {
    float_server_target_cash_current = 0;
    float_server_used_ram_free_current -= integer_threads_hack * object_scripts.hack.ram;
    const integer_threads_hack = integer_get_threads_hack(ns, float_server_used_ram_free_current, string_server_target, float_server_target_security_current, float_get_percentage_to_steal(ns, float_server_used_ram_free_current, string_server_target, float_server_target_cash_current, float_server_target_security_current, float_precision, float_steal_cap));
    if (!boolean_can_server_run_script_threads(ns, float_server_used_ram_free_current, object_scripts.hack.ram, 1)) {
    // start using a server with more ram
    boolean_end_loop_server = true;
    ++integer_array_schedule_length;
    schedule_item.integer_time_job_finishes_seconds = integer_time_job_finishes_seconds;
    integer_time_job_finishes_seconds += float_padding_seconds;
    schedule_item.float_server_target_security_current = float_server_target_security_current;
    schedule_item.float_delay_seconds = integer_time_job_finishes_seconds - float_time_grow + float_padding_seconds;
    float_server_target_security_current += float_get_security_increase_from_grow(ns, integer_threads_grow);
    const float_server_target_cash_current_uncorrected = float_server_target_cash_current * float_get_growth_from_threads(ns, string_server_target, float_server_target_security_current, integer_threads_grow);
    }
    if (float_server_target_cash_current === 0) {
    float_server_target_cash_current = 1; // counts 0 cash as 1 so it can still grow. taken from `grow` in NetscriptFunctions.js
    if (!boolean_can_server_run_script_threads(ns, float_server_used_ram_free_current, object_scripts.grow.ram, 1)) {
    // start using a server with more ram
    boolean_end_loop_server = true;
    ++integer_array_schedule_length;
    schedule_item.integer_time_job_finishes_seconds = integer_time_job_finishes_seconds;
    integer_time_job_finishes_seconds += float_padding_seconds;
    schedule_item.float_delay_seconds = integer_time_job_finishes_seconds - float_time_weaken + float_padding_seconds;
    schedule_item.float_server_target_security_current = float_server_target_security_current;
    const float_server_target_security_uncorrected = float_server_target_security_current - float_get_security_decrease_from_weaken(ns, integer_threads_weaken);
    if (!boolean_can_server_run_script_threads(ns, float_server_used_ram_free_current, object_scripts.weaken.ram, 1)) {
    // start using a server with more ram
    boolean_end_loop_server = true;
    switch (string_job) {
    case "": {
    boolean_end_loop_array_servers = true;
    break;
    }
    string_job: string_job,
    while (
    float_server_used_ram_free_current > 0 &&
    ) {
    const string_job = string_decider(ns, string_server_target, float_server_target_security_current, float_server_target_cash_current);
    const schedule_item = {
    integer_array_schedule_length < integer_job_cap &&
    !boolean_end_loop_array_servers &&
    !boolean_end_loop_server
    // iterate through servers in reverse to use servers with the biggest rams first
    for (let integer_indices_0 = array_servers_rooted_sorted_by_ram.length - 1; integer_indices_0 >= 0; --integer_indices_0) {
    break;
    }
    if (integer_array_schedule_length >= integer_job_cap ||
    boolean_end_loop_array_servers) {
    let integer_time_job_finishes_seconds = float_time_weaken;
    let integer_array_schedule_length = 0;
    // tripwires
    let boolean_end_loop_array_servers = false;
    let boolean_end_loop_server = false;
    const array_servers_rooted_sorted_by_ram = array_get_servers_rooted_sorted_by_ram(ns);
    // makes a schedule
    const array_make_schedule = function(ns, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target, string_decider) {
    return weakenTimeMultiplier * float_get_time_hack(ns, string_server_target, float_server_target_security);
    const float_get_time_weaken = function(ns, string_server_target, float_server_target_security) {
    return growTimeMultiplier * float_get_time_hack(ns, string_server_target, float_server_target_security);
    const float_get_time_grow = function(ns, string_server_target, float_server_target_security) {
    const hack = object_constants.object_stats.hacking;
    const int = object_constants.object_stats.intelligence;
    const float_get_time_hack = function(ns, string_server_target, float_server_target_security) {
    const boolean_can_server_run_script_threads = function(ns, float_server_used_ram_free, float_script_ram, integer_threads) {
    const string_job_decider_prepare = function(ns, string_server_target, float_server_target_security, float_server_target_cash) {
    if (float_server_target_security > ns.getServerMinSecurityLevel(string_server_target)) {
    return "weaken";
    }
    if (float_server_target_cash < ns.getServerMaxMoney(string_server_target)) {
    return "grow";
    }
    return "";
    };
    const string_job_decider = function(ns, string_server_target, float_server_target_security, float_server_target_cash) {
    ns.scp(array_files[integer_indices_1], string_source, array_servers_rooted[integer_indices_0]);
    if (float_percentage_to_steal > float_steal_cap) {
    return float_steal_cap;
    if (float_percentage_to_steal > float_steal_cap) {
    break;
    }
    for (let integer_indices_0 = 0; integer_indices_0 < integer_cycles_for_bisection_precision; ++integer_indices_0) {
    if (boolean_is_ram_enough_after_hack_percentage(ns, float_server_used_ram_free, string_server_target, float_server_target_cash, float_server_target_security, float_percentage_to_steal)) {
    const integer_cycles_for_bisection_precision = integer_get_cycles_for_bisection_precision(ns, float_precision);
    // this should return optimum percentage to steal such that cash stolen at most is as high as float_steal_cap and string_server_target's security is able to be weakened to minimum with one weaken after the hack, its cash grown to 100% after one grow after the weaken, then its security weakened again to minimum with one weaken, all with the ram it has remaining after the hack by using a binary search algorithm
    const float_get_percentage_to_steal = function(ns, float_server_used_ram_free, string_server_target, float_server_target_cash, float_server_target_security, float_precision, float_steal_cap) {
    const integer_get_cycles_for_bisection_precision = function(ns, float_precision) {
    return false;
    const float_server_target_security_after_hack = float_server_target_security + float_get_security_increase_from_hack(ns, string_server_target, float_server_target_security, float_server_target_cash, integer_get_threads_hack(ns, float_server_used_ram_free, string_server_target, float_server_target_security, float_percentage_to_steal));
    const integer_threads_required_for_weaken_minimum_security_after_hack = integer_get_threads_required_for_weaken_minimum_security(ns, string_server_target, float_server_target_security_after_hack);
    const float_server_target_security_after_weaken = float_server_target_security_after_hack - float_get_security_decrease_from_weaken(ns, integer_threads_required_for_weaken_minimum_security_after_hack);
    const integer_threads_required_for_cash_grow_after_percentage_stolen = integer_get_threads_required_for_cash_grow_after_percentage_stolen(ns, string_server_target, float_server_target_security_after_weaken, float_percentage_to_steal);
    const float_server_target_security_after_grow = float_server_target_security_after_weaken + float_get_security_increase_from_grow(ns,integer_threads_required_for_cash_grow_after_percentage_stolen);
    const integer_threads_required_for_weaken_minimum_security_after_grow = integer_get_threads_required_for_weaken_minimum_security(ns, string_server_target, float_server_target_security_after_grow);
    if (float_ram_required < float_server_used_ram_free) {
    return true;
    const float_ram_required = (integer_threads_required_for_weaken_minimum_security_after_hack * object_scripts.weaken.ram) + (integer_threads_required_for_cash_grow_after_percentage_stolen * object_scripts.grow.ram) + (integer_threads_required_for_weaken_minimum_security_after_grow * object_scripts.weaken.ram);
    const object_scripts = object_get_constants(ns).object_scripts;
    // should return true if there is enough ram to provide the threads required by weaken to weaken to minimum security, then by grow to grow string_server_target's cash back to maximum after stealing float_percentage_to_steal of the cash, then by weaken to weaken to minimum security again if possible, otherwise, returns false. assumes security is at float_server_target_security
    const boolean_is_ram_enough_after_hack_percentage = function(ns, float_server_used_ram_free, string_server_target, float_server_target_cash, float_server_target_security, float_percentage_to_steal) {
    };
    // returns the security increase from the hack threads. adapted from `hack` in NetscriptFunctions.js and `fortify` in Server.ts
    const float_get_security_increase_from_hack = function(ns, string_server_target, float_server_target_security, float_server_target_cash, integer_threads_hack) {
    let maxThreadNeeded = Math.ceil(1/float_get_percentage_of_cash_from_available_per_hack(ns, string_server_target, float_server_target_security)*(float_server_target_cash/ns.getServerMaxMoney(string_server_target)));
    if (isNaN(maxThreadNeeded)) {
    // Server has a 'max money' of 0 (probably). We'll set this to an arbitrarily large value
    maxThreadNeeded = 1e6;
    }
    return object_get_constants(ns).ServerFortifyAmount * Math.min(integer_threads_hack, maxThreadNeeded);
    const integer_threads_required = integer_get_threads_required_to_hack_percentage(ns, string_server_target, float_server_target_security, float_percentage_to_steal);
    return Math.ceil(float_percentage_to_steal / float_get_percentage_of_cash_from_available_per_hack(ns, string_server_target, float_server_target_security));
    const integer_get_threads_required_to_hack_percentage = function(ns, string_server_target, float_server_target_security, float_percentage_to_steal) {
    const skillMult = (ns.getHackingLevel() - (ns.getServerRequiredHackingLevel(string_server_target) - 1)) / ns.getHackingLevel();
    const percentMoneyHacked = difficultyMult * skillMult * object_constants.object_hacking_multipliers.money / balanceFactor;
    if (percentMoneyHacked < 0) { return 0; }
    if (percentMoneyHacked > 1) { return 1; }
    };
    // returns the security increase from the growth threads used. Adapted from `processSingleServerGrowth` in ServerHelpers.ts and `fortify` in Server.ts
    const float_get_security_increase_from_grow = function(ns, integer_threads_grow) {
    return 2 * object_get_constants(ns).ServerFortifyAmount * integer_threads_grow;
    const integer_threads_required = integer_get_threads_required_for_grow_maximum_cash(ns, string_server_target, float_server_target_security, float_server_target_cash);
    const integer_get_threads_required_for_grow_maximum_cash = function(ns, string_server_target, float_server_target_security, float_server_target_cash) {
    };
    // returns the security decrease from the weaken threads used. Adapted from `weaken` in NetscriptFunctions.js and `weaken` in Server.ts
    const float_get_security_decrease_from_weaken = function(ns, integer_threads_weaken) {
    return integer_threads_weaken * object_get_constants(ns).ServerWeakenAmount;
    const integer_threads_required = integer_get_threads_required_for_weaken_minimum_security(ns, string_server_target, float_server_target_security);
    const integer_get_threads_required_for_weaken_minimum_security = function(ns, string_server_target, float_server_target_security) {
    return array_servers.sort((string_element_0, string_element_1) => float_get_server_score(ns, string_element_0) - float_get_server_score(ns, string_element_1));
    // sort an array of servers by their score, from lowest to highest
    const float_player_hacking_level = ns.getHackingLevel();
    return ns.getServerMaxMoney(string_server_target) * ns.getServerGrowth(string_server_target) * ((float_player_hacking_level - (ns.getServerRequiredHackingLevel(string_server_target) - 1)) * Math.pow(float_player_hacking_level, -1));
    // returns the score of a server which is calculated by taking into account its max cash, growth, and required hacking level. adapted from `calculatePercentMoneyHacked` in Hacking.js
    const float_get_server_score = function(ns, string_server_target) {
    ns.tprint(JSON.stringify(error));
    ns.tprint(JSON.stringify(error));
    };
    while (boolean_conditions_server_delete_purchase(ns)) {
    ns.deleteServer(string_get_server_bought_smallest(ns));
    ns.purchaseServer(string_name, integer_get_server_ram_biggest_afforded(ns));
    }
    while (
    boolean_conditions_server_purchase_3(ns) ||
    boolean_conditions_server_purchase_2(ns) ||
    boolean_conditions_server_purchase_1(ns)
    ) {
    ns.purchaseServer(string_name, integer_get_server_ram_biggest_afforded(ns));
    (ns.getServerMoneyAvailable("home") >= 3 * object_constants.BaseCostFor1GBOfRamServer * integer_get_server_ram_total(ns, string_get_server_bought_smallest(ns)))
    ) {
    return true;
    }
    else {
    return false;
    !(boolean_servers_bought_all_max(ns, object_constants.PurchasedServerMaxRam)) &&
    };
    const boolean_conditions_server_delete_purchase = function(ns) {
    const object_constants = object_get_constants(ns);
    if (// you currently own the maximum amount of purchased servers allowed
    (ns.getPurchasedServers().length == object_constants.PurchasedServerLimit) &&
    ) {
    if (// you already bought a server with max ram, buy another server the max possible ram
    (integer_get_server_ram_total(ns, string_get_server_bought_biggest(ns)) == float_ram_server_bought_maximum) &&
    (integer_get_server_ram_biggest_afforded(ns) >= float_ram_server_bought_maximum)
    ) {
    return true;
    }
    ) {
    }
    };
    const boolean_conditions_server_purchase_3 = function(ns) {
    const integer_servers_bought_amount = ns.getPurchasedServers().length;
    const object_constants = object_get_constants(ns);
    const float_ram_server_bought_maximum = object_constants.PurchasedServerMaxRam;
    if (// you have one or more servers already
    (integer_servers_bought_amount > 0) &&
    // you currently own less than the maximum amount of purchased servers allowed
    (integer_servers_bought_amount < object_constants.PurchasedServerLimit)
    const float_ram_server_bought_biggest = integer_get_server_ram_total(ns, string_get_server_bought_biggest(ns));
    if (
    // you dont own a server with max ram yet, buy a server with ram greater than the ram of your biggest bought server
    (float_ram_server_bought_biggest != object_constants.PurchasedServerMaxRam) &&
    (float_ram_server_bought_biggest < integer_get_server_ram_biggest_afforded(ns))
    ) {
    return true;
    }
    const boolean_conditions_server_purchase_1 = function(ns) {
    const integer_server_ram_biggest_afforded = integer_get_server_ram_biggest_afforded(ns);
    const object_constants = object_get_constants(ns);
    (integer_server_ram_biggest_afforded >= object_constants.integer_server_ram_min) &&
    ) {
    return true;
    }
    };
    const boolean_conditions_server_purchase_2 = function(ns) {
    const integer_servers_bought_amount = ns.getPurchasedServers().length;
    if (// you have one or more servers already
    (integer_servers_bought_amount > 0) &&
    // you currently own less than the maximum amount of purchased servers allowed
    (integer_servers_bought_amount < object_constants.PurchasedServerLimit)
    const object_constants = object_get_constants(ns);
    // ram is at least equal to the ram of "home" (probably a bad idea to hardcode this since the string_name of "home" might change in the future) or max ram.
    (integer_server_ram_biggest_afforded >= integer_get_server_ram_total(ns, "home") ||
    integer_server_ram_biggest_afforded >= object_constants.PurchasedServerMaxRam)
    if (// you have no bought servers yet
    (ns.getPurchasedServers().length === 0) &&
    // ram is at least equal to the minimum ram possible for purchased servers
    // continually buys the best server with cash available, unless there are 25 servers already, in which case deletes the worst server, unless all 25 have ram == PurchasedServerMaxRam
    let integer_server_ram_biggest_afforded = Math.pow(2, Math.trunc(Math.log2(ns.getServerMoneyAvailable("home") / object_constants.BaseCostFor1GBOfRamServer) / Math.log2(2)));
    };
    // tries to continually buy ram as long as you have sufficient cash
    const void_buy_home_ram = function(ns) {
    // let float_cash_current = getServerMoneyAvailable("home");
    // try {
    // while (float_cash_current >= getUpgradeHomeRamCost()) {
    // ns.upgradeHomeRam();
    // float_cash_current = getServerMoneyAvailable("home");
    // }
    // }
    // }
    // catch (error) {
    // ns.tprint(JSON.stringify(error));
    // name of current host (usually "home")
    // object_constants are from https://github.com/danielyxie/bitburner/blob/master/src/Constants.js
    // ns.tprint(JSON.stringify(error));
    // ns.tprint(JSON.stringify(error));
    // from BitNode/BitNodeMultipliers
  • replacement in bin/main.js at line 1
    [5.3793719][5.4231:4766](),[5.4766][5.2481:2482](),[5.2481][5.2481:2482](),[5.2482][5.3793720:3793740](),[5.3793719][5.3793720:3793740](),[5.3793740][5.6028:6042](),[5.6042][5.3793763:3793780](),[5.3793763][5.3793763:3793780]()
    // TODO: Separate logic that can finish running (e.g. server buying logic which becomes redundant after 25 fully upgraded servers have been bought) to other sbins so that RAM usage is more efficient. Also separate logic that requires source files so that they are only ran when you have the required source file. Maybe make a cache script that saves runtime constants like max money of servers to a cache file to potentially reduce RAM usage further. Maybe add functionality that allows on-the-fly hot loading of settings from a file.
    // imports
    import {
    void_runner
    } from "lib.js";
    [5.3793719]
    [5.3793780]
    // main.js - 9.1GB - TODO: Separate logic that requires source files so that they are only ran when you have the required source file - need a cheap way to check if you have source file? Maybe make a cache script that saves runtime constants like max money of servers to a cache file to potentially reduce RAM usage further. Maybe add functionality that allows on-the-fly hot loading of settings from a file.
  • edit in bin/main.js at line 3
    [5.3793781]
    [5.3793781]
    // main
  • replacement in bin/main.js at line 20
    [5.2324][5.2324:2359]()
    let string_server_target = null;
    [5.2324]
    [5.2359]
    let string_server_target = "";
  • replacement in bin/main.js at line 75
    [5.3794595][5.6043:6233]()
    integer_time_finishes = await void_runner(ns, string_servers_bought_name, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target) + Date.now();
    [5.3794595]
    [5.3794956]
    integer_time_finishes = await void_runner(ns, string_servers_bought_name, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target, float_period_check_seconds) + Date.now();
  • edit in bin/main.js at line 79
    [5.3795163]
    [5.3795163]
    }
    };
    // functions
    const object_get_constants = function(ns) {
    // from BitNode/BitNodeMultipliers
    const object_get_bitnode_multipliers = function(ns) {
    // try {
    // return ns.getBitNodeMultipliers();
    // }
    // catch (error) {
    // ns.tprint(JSON.stringify(error));
    // return {
    // HackingLevelMultiplier: 1,
    // StrengthLevelMultiplier: 1,
    // DefenseLevelMultiplier: 1,
    // DexterityLevelMultiplier: 1,
    // AgilityLevelMultiplier: 1,
    // CharismaLevelMultiplier: 1,
    // ServerGrowthRate: 1,
    // ServerMaxMoney: 1,
    // ServerStartingMoney: 1,
    // ServerStartingSecurity: 1,
    // ServerWeakenRate: 1,
    // HomeComputerRamCost: 1,
    // PurchasedServerCost: 1,
    // PurchasedServerLimit: 1,
    // PurchasedServerMaxRam: 1,
    // CompanyWorkMoney: 1,
    // CrimeMoney: 1,
    // HacknetNodeMoney: 1,
    // ManualHackMoney: 1,
    // ScriptHackMoney: 1,
    // CodingContractMoney: 1,
    // ClassGymExpGain: 1,
    // CompanyWorkExpGain: 1,
    // CrimeExpGain: 1,
    // FactionWorkExpGain: 1,
    // HackExpGain: 1,
    // FactionPassiveRepGain: 1,
    // FactionWorkRepGain: 1,
    // RepToDonateToFaction: 1,
    // AugmentationMoneyCost: 1,
    // AugmentationRepCost: 1,
    // InfiltrationMoney: 1,
    // InfiltrationRep: 1,
    // FourSigmaMarketDataCost: 1,
    // FourSigmaMarketDataApiCost: 1,
    // CorporationValuation: 1,
    // BladeburnerRank: 1,
    // BladeburnerSkillCost: 1,
    // DaedalusAugsRequirement: 1,
    // };
    // }
    return {
    HackingLevelMultiplier: 1,
    StrengthLevelMultiplier: 1,
    DefenseLevelMultiplier: 1,
    DexterityLevelMultiplier: 1,
    AgilityLevelMultiplier: 1,
    CharismaLevelMultiplier: 1,
    ServerGrowthRate: 1,
    ServerMaxMoney: 1,
    ServerStartingMoney: 1,
    ServerStartingSecurity: 1,
    ServerWeakenRate: 1,
    HomeComputerRamCost: 1,
    PurchasedServerCost: 1,
    PurchasedServerLimit: 1,
    PurchasedServerMaxRam: 1,
    CompanyWorkMoney: 1,
    CrimeMoney: 1,
    HacknetNodeMoney: 1,
    ManualHackMoney: 1,
    ScriptHackMoney: 1,
    CodingContractMoney: 1,
    ClassGymExpGain: 1,
    CompanyWorkExpGain: 1,
    CrimeExpGain: 1,
    FactionWorkExpGain: 1,
    HackExpGain: 1,
    FactionPassiveRepGain: 1,
    FactionWorkRepGain: 1,
    RepToDonateToFaction: 1,
    AugmentationMoneyCost: 1,
    AugmentationRepCost: 1,
    InfiltrationMoney: 1,
    InfiltrationRep: 1,
    FourSigmaMarketDataCost: 1,
    FourSigmaMarketDataApiCost: 1,
    CorporationValuation: 1,
    BladeburnerRank: 1,
    BladeburnerSkillCost: 1,
    DaedalusAugsRequirement: 1,
    };
    };
    const object_get_stats = function(ns) {
    // try {
    // return ns.getStats();
    // }
    // catch (error) {
    // ns.tprint(JSON.stringify(error));
    // return {
    // hacking: ns.getHackingLevel(),
    // strength: 1,
    // defense: 1,
    // dexterity: 1,
    // agility: 1,
    // charisma: 1,
    // intelligence: 1
    // };
    // }
    return {
    hacking: ns.getHackingLevel(),
    strength: 1,
    defense: 1,
    dexterity: 1,
    agility: 1,
    charisma: 1,
    intelligence: 1
    };
    };
    // object_constants are from https://github.com/danielyxie/bitburner/blob/master/src/Constants.js
    const object_constants = {
    // factor used in determining the amount security increases by from a grow or hack
    ServerFortifyAmount: 0.002,
    // amount security decreases by from a weaken
    ServerWeakenAmount: 0.05,
    // base percentage cash increases by from a grow
    ServerBaseGrowthRate: 1.03,
    // max percentage cash increases by from a grow (accounts for server security)
    ServerMaxGrowthRate: 1.0035,
    // hacking multipliers
    object_hacking_multipliers: ns.getHackingMultipliers(),
    // bitnode multipliers
    object_bitnode_multipliers: object_get_bitnode_multipliers(ns),
    // player stats
    object_stats: object_get_stats(ns),
    // filenames and ram cost of helper object_scripts
    object_scripts: {
    weaken: {
    file: "weaken.js",
    ram: 1.75 // or ns.getScriptRam(object_get_constants(ns).object_scripts.weaken.file);
    },
    grow: {
    file: "grow.js",
    ram: 1.75 // or ns.getScriptRam(object_get_constants(ns).object_scripts.grow.file);
    },
    hack: {
    file: "hack.js",
    ram: 1.7 // or ns.getScriptRam(object_get_constants(ns).object_scripts.hack.file);
    }
    },
    // name of current host (usually "home")
    string_host: "home" // or ns.getHostname()
    };
    return object_constants;
    };
    // returns an array of all servers in the game
    const array_get_servers = function(ns) {
    const string_host = object_get_constants(ns).string_host;
    const array_servers = [string_host];
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers.length; ++integer_indices_0) {
    const array_scan_results = ns.scan(array_servers[integer_indices_0]);
    for (let integer_indices_1 = 0; integer_indices_1 < array_scan_results.length; ++integer_indices_1) {
    if (array_servers.indexOf(array_scan_results[integer_indices_1]) === -1) {
    array_servers.push(array_scan_results[integer_indices_1]);
    }
    }
    }
    return array_servers;
    };
    // returns the total ram of a server
    const integer_get_server_ram_total = function(ns, string_server) {
    return (ns.getServerRam(string_server))[0];
    };
    // returns the used ram of a server
    const float_get_server_ram_used = function(ns, string_server) {
    return (ns.getServerRam(string_server))[1];
    };
    // returns the amount of free ram of a server
    const float_get_server_ram_free = function(ns, string_server) {
    return integer_get_server_ram_total(ns, string_server) - float_get_server_ram_used(ns, string_server);
    };
    // targetting
    // sort an array of servers by their amounts of RAM, from lowest to highest
    const void_sort_by_server_ram = function(ns, array_servers) {
    return array_servers.sort((string_element_0, string_element_1) => (integer_get_server_ram_total(ns, string_element_0) - integer_get_server_ram_total(ns, string_element_1)));
    };
    // returns the score of a server which is calculated by taking into account its max cash, growth, and required hacking level. adapted from `calculatePercentMoneyHacked` in Hacking.js
    const float_get_server_score = function(ns, string_server_target) {
    const float_player_hacking_level = ns.getHackingLevel();
    return ns.getServerMaxMoney(string_server_target) * ns.getServerGrowth(string_server_target) * ((float_player_hacking_level - (ns.getServerRequiredHackingLevel(string_server_target) - 1)) * Math.pow(float_player_hacking_level, -1));
    };
    // sort an array of servers by their score, from lowest to highest
    const void_sort_by_server_scores = function(ns, array_servers) {
    return array_servers.sort((string_element_0, string_element_1) => float_get_server_score(ns, string_element_0) - float_get_server_score(ns, string_element_1));
    };
    // weaken, grow, hack
    // returns an array of all rooted servers
    const array_get_servers_rooted = function(ns) {
    const array_servers = array_get_servers(ns);
    const array_servers_rooted = [];
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers.length; ++integer_indices_0) {
    if (ns.hasRootAccess(array_servers[integer_indices_0])) {
    array_servers_rooted.push(array_servers[integer_indices_0]);
    }
    }
    return array_servers_rooted;
    };
    // returns integer_threads_required if it's less than or equal to integer_threads_available, otherwise returns integer_threads_available
    const integer_get_corrected_threads = function(ns, integer_threads_required, integer_threads_available) {
    if (integer_threads_required > integer_threads_available) {
    return integer_threads_available;
    }
    else {
    return integer_threads_required;
    }
    };
    // weaken stuff
    // the threads required for weaken to cause string_server_target's security to decrease by float_weaken_amount. adapted from `weaken` in NetscriptFunctions.js and `weaken` in Server.ts
    const integer_get_threads_required_for_weaken = function(ns, float_weaken_amount) {
    const object_constants = object_get_constants(ns);
    return float_weaken_amount * Math.pow(object_constants.ServerWeakenAmount, -1) * Math.pow(object_constants.object_bitnode_multipliers.ServerWeakenRate, -1);
    };
    // returns the threads required for weaken to cause string_server_target's security to reach minimum
    const integer_get_threads_required_for_weaken_minimum_security = function(ns, string_server_target, float_server_target_security) {
    return Math.ceil(integer_get_threads_required_for_weaken(ns, float_server_target_security - ns.getServerMinSecurityLevel(string_server_target)));
    };
    // returns the threads required for weaken to cause string_server_target's security to reach minimum if possible, otherwise, return max threads that string_server_used can provide
    const integer_get_threads_weaken = function(ns, float_server_used_ram_free, string_server_target, float_server_target_security) {
    const integer_threads_available = Math.trunc(float_server_used_ram_free / object_get_constants(ns).object_scripts.weaken.ram);
    const integer_threads_required = integer_get_threads_required_for_weaken_minimum_security(ns, string_server_target, float_server_target_security);
    return integer_get_corrected_threads(ns, integer_threads_required, integer_threads_available);
    };
    // returns the security decrease from the weaken threads used. Adapted from `weaken` in NetscriptFunctions.js and `weaken` in Server.ts
    const float_get_security_decrease_from_weaken = function(ns, integer_threads_weaken) {
    return integer_threads_weaken * object_get_constants(ns).ServerWeakenAmount;
    };
    // grow stuff
    // returns the number of threads of `grow` needed to grow `string_server_target` by the percentage `float_growth` when it has security of `float_server_security`. float_growth = How much the server is being grown by, in DECIMAL form (e.g. 1.5 rather than 50). adapted from `numCycleForGrowth` in https://github.com/danielyxie/bitburner/blob/master/src/Server/ServerHelpers.ts
    const integer_get_threads_for_growth = function(ns, string_server_target, float_server_target_security, float_growth) {
    const object_constants = object_get_constants(ns);
    let ajdGrowthRate = 1 + (object_constants.ServerBaseGrowthRate - 1) / float_server_target_security;
    if (ajdGrowthRate > object_constants.ServerMaxGrowthRate) {
    ajdGrowthRate = object_constants.ServerMaxGrowthRate;
    }
    const serverGrowthPercentage = ns.getServerGrowth(string_server_target) / 100;
    const cycles = Math.log(float_growth)/(Math.log(ajdGrowthRate) * object_constants.object_hacking_multipliers.growth * serverGrowthPercentage * object_constants.object_bitnode_multipliers.ServerGrowthRate);
    return Math.ceil(cycles);
    };
    // Inverse function of integer_get_threads_for_growth. Returns the percentage growth in decimal form (e.g., 2 = 100% growth).
    const float_get_growth_from_threads = function(ns, string_server_target, float_server_target_security, integer_threads) {
    const object_constants = object_get_constants(ns);
    let ajdGrowthRate = 1 + (object_constants.ServerBaseGrowthRate - 1) / float_server_target_security;
    if (ajdGrowthRate > object_constants.ServerMaxGrowthRate) {
    ajdGrowthRate = object_constants.ServerMaxGrowthRate;
    }
    const serverGrowthPercentage = ns.getServerGrowth(string_server_target) / 100;
    const float_growth = Math.pow(ajdGrowthRate, integer_threads * object_constants.object_hacking_multipliers.growth * serverGrowthPercentage * object_constants.object_bitnode_multipliers.ServerGrowthRate);
    return float_growth;
    };
    // returns the threads required by grow to grow string_server_target's cash to its maximum when security is at float_server_target_security and current cash is at float_server_target_cash
    const integer_get_threads_required_for_grow_maximum_cash = function(ns, string_server_target, float_server_target_security, float_server_target_cash) {
    return integer_get_threads_for_growth(ns, string_server_target, float_server_target_security, ns.getServerMaxMoney(string_server_target) / float_server_target_cash);
    };
    // returns the threads required by grow to grow string_server_target's cash to its maximum if possible, otherwise, return max threads that string_server_used can provide
    const integer_get_threads_grow = function(ns, float_server_used_ram_free, string_server_target, float_server_target_security, float_server_target_cash) {
    const integer_threads_available = Math.trunc(float_server_used_ram_free / object_get_constants(ns).object_scripts.grow.ram);
    const integer_threads_required = integer_get_threads_required_for_grow_maximum_cash(ns, string_server_target, float_server_target_security, float_server_target_cash);
    return integer_get_corrected_threads(ns, integer_threads_required, integer_threads_available);
    };
    // returns the security increase from the growth threads used. Adapted from `processSingleServerGrowth` in ServerHelpers.ts and `fortify` in Server.ts
    const float_get_security_increase_from_grow = function(ns, integer_threads_grow) {
    return 2 * object_get_constants(ns).ServerFortifyAmount * integer_threads_grow;
    };
    // hack stuff
    // returns the percentage of the available cash in string_server_target that is stolen when it is hacked when it has float_server_target_security. adapted from calculatePercentMoneyHacked() in https://github.com/danielyxie/bitburner/blob/master/src/Hacking.js . See also `hackDifficulty` in https://github.com/danielyxie/bitburner/blob/master/src/Server.js
    const float_get_percentage_of_cash_from_available_per_hack = function(ns, string_server_target, float_server_target_security) {
    const object_constants = object_get_constants(ns);
    const balanceFactor = 240;
    const difficultyMult = (100 - float_server_target_security) / 100;
    const skillMult = (ns.getHackingLevel() - (ns.getServerRequiredHackingLevel(string_server_target) - 1)) / ns.getHackingLevel();
    const percentMoneyHacked = difficultyMult * skillMult * object_constants.object_hacking_multipliers.money / balanceFactor;
    if (percentMoneyHacked < 0) { return 0; }
    if (percentMoneyHacked > 1) { return 1; }
    return percentMoneyHacked * object_constants.object_bitnode_multipliers.ScriptHackMoney;
    };
    // returns the threads required to steal "float_percentage_to_steal" of available money in string_server_target
    const integer_get_threads_required_to_hack_percentage = function(ns, string_server_target, float_server_target_security, float_percentage_to_steal) {
    return Math.ceil(float_percentage_to_steal / float_get_percentage_of_cash_from_available_per_hack(ns, string_server_target, float_server_target_security));
    };
    // returns the threads required to steal "float_percentage_to_steal" of available money in string_server_target if possible, otherwise, return max threads that string_server_used can provide
    const integer_get_threads_hack = function(ns, float_server_used_ram_free, string_server_target, float_server_target_security, float_percentage_to_steal) {
    const integer_threads_available = Math.trunc(float_server_used_ram_free / object_get_constants(ns).object_scripts.hack.ram);
    const integer_threads_required = integer_get_threads_required_to_hack_percentage(ns, string_server_target, float_server_target_security, float_percentage_to_steal);
    return integer_get_corrected_threads(ns, integer_threads_required, integer_threads_available);
    };
    // returns the security increase from the hack threads. adapted from `hack` in NetscriptFunctions.js and `fortify` in Server.ts
    const float_get_security_increase_from_hack = function(ns, string_server_target, float_server_target_security, float_server_target_cash, integer_threads_hack) {
    let maxThreadNeeded = Math.ceil(1/float_get_percentage_of_cash_from_available_per_hack(ns, string_server_target, float_server_target_security)*(float_server_target_cash/ns.getServerMaxMoney(string_server_target)));
    if (isNaN(maxThreadNeeded)) {
    // Server has a 'max money' of 0 (probably). We'll set this to an arbitrarily large value
    maxThreadNeeded = 1e6;
  • edit in bin/main.js at line 447
    [5.3795167]
    [5.3795167]
    return object_get_constants(ns).ServerFortifyAmount * Math.min(integer_threads_hack, maxThreadNeeded);
    };
    // percentage to steal stuff
    // returns the threads required by grow to grow a string_server_target's money back to its original value after stealing float_percentage_to_steal of it, and assuming security is at float_server_target_security
    const integer_get_threads_required_for_cash_grow_after_percentage_stolen = function(ns, string_server_target, float_server_target_security, float_percentage_to_steal) {
    return integer_get_threads_for_growth(ns, string_server_target, float_server_target_security, Math.pow(1 - float_percentage_to_steal, -1));
    };
    // should return true if there is enough ram to provide the threads required by weaken to weaken to minimum security, then by grow to grow string_server_target's cash back to maximum after stealing float_percentage_to_steal of the cash, then by weaken to weaken to minimum security again if possible, otherwise, returns false. assumes security is at float_server_target_security
    const boolean_is_ram_enough_after_hack_percentage = function(ns, float_server_used_ram_free, string_server_target, float_server_target_cash, float_server_target_security, float_percentage_to_steal) {
    const object_scripts = object_get_constants(ns).object_scripts;
    const float_server_target_security_after_hack = float_server_target_security + float_get_security_increase_from_hack(ns, string_server_target, float_server_target_security, float_server_target_cash, integer_get_threads_hack(ns, float_server_used_ram_free, string_server_target, float_server_target_security, float_percentage_to_steal));
    const integer_threads_required_for_weaken_minimum_security_after_hack = integer_get_threads_required_for_weaken_minimum_security(ns, string_server_target, float_server_target_security_after_hack);
    const float_server_target_security_after_weaken = float_server_target_security_after_hack - float_get_security_decrease_from_weaken(ns, integer_threads_required_for_weaken_minimum_security_after_hack);
    const integer_threads_required_for_cash_grow_after_percentage_stolen = integer_get_threads_required_for_cash_grow_after_percentage_stolen(ns, string_server_target, float_server_target_security_after_weaken, float_percentage_to_steal);
    const float_server_target_security_after_grow = float_server_target_security_after_weaken + float_get_security_increase_from_grow(ns,integer_threads_required_for_cash_grow_after_percentage_stolen);
    const integer_threads_required_for_weaken_minimum_security_after_grow = integer_get_threads_required_for_weaken_minimum_security(ns, string_server_target, float_server_target_security_after_grow);
    const float_ram_required = (integer_threads_required_for_weaken_minimum_security_after_hack * object_scripts.weaken.ram) + (integer_threads_required_for_cash_grow_after_percentage_stolen * object_scripts.grow.ram) + (integer_threads_required_for_weaken_minimum_security_after_grow * object_scripts.weaken.ram);
    if (float_ram_required < float_server_used_ram_free) {
    return true;
    }
    else {
    return false;
    }
    };
    // returns the number of cycles of bisection to be done to reach a certain precision, rounded up to the nearest integer
    const integer_get_cycles_for_bisection_precision = function(ns, float_precision) {
    return Math.ceil(Math.log(Math.pow(float_precision, -1)) * Math.pow(Math.log(2), -1));
    };
    // this should return optimum percentage to steal such that cash stolen at most is as high as float_steal_cap and string_server_target's security is able to be weakened to minimum with one weaken after the hack, its cash grown to 100% after one grow after the weaken, then its security weakened again to minimum with one weaken, all with the ram it has remaining after the hack by using a binary search algorithm
    const float_get_percentage_to_steal = function(ns, float_server_used_ram_free, string_server_target, float_server_target_cash, float_server_target_security, float_precision, float_steal_cap) {
    const integer_cycles_for_bisection_precision = integer_get_cycles_for_bisection_precision(ns, float_precision);
    let float_ceiling = 1;
    let float_floor = 0;
    let float_percentage_to_steal = (float_ceiling + float_floor) * 0.5;
    for (let integer_indices_0 = 0; integer_indices_0 < integer_cycles_for_bisection_precision; ++integer_indices_0) {
    if (boolean_is_ram_enough_after_hack_percentage(ns, float_server_used_ram_free, string_server_target, float_server_target_cash, float_server_target_security, float_percentage_to_steal)) {
    float_floor = float_percentage_to_steal;
    }
    else {
    float_ceiling = float_percentage_to_steal;
    }
    float_percentage_to_steal = (float_ceiling + float_floor) * 0.5;
    if (float_percentage_to_steal > float_steal_cap) {
    break;
    }
    }
    // cap which can be used so not all money is stolen, which can be bad because it's harder to grow from 0 in most cases
    if (float_percentage_to_steal > float_steal_cap) {
    return float_steal_cap;
    }
    else {
    return float_percentage_to_steal;
    }
    };
    // copies files to all rooted servers
    const void_copy_files_to_string_servers_rooted = function(ns, array_files, string_source) {
    const array_servers_rooted = array_get_servers_rooted(ns);
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers_rooted.length; ++integer_indices_0) {
    for (let integer_indices_1 = 0; integer_indices_1 < array_files.length; ++integer_indices_1) {
    ns.scp(array_files[integer_indices_1], string_source, array_servers_rooted[integer_indices_0]);
    }
    }
    };
    // scheduling
    const array_get_servers_rooted_sorted_by_ram = function(ns) {
    let array_servers_rooted = array_get_servers_rooted(ns);
    void_sort_by_server_ram(ns, array_servers_rooted);
    return array_servers_rooted;
    };
    const array_get_servers_rooted_sorted_by_score = function(ns) {
    let array_servers_rooted = array_get_servers_rooted(ns);
    void_sort_by_server_scores(ns, array_servers_rooted);
    return array_servers_rooted;
    };
    const string_get_server_rooted_hackable_with_score_biggest = function(ns) {
    const array_servers_rooted_sorted_by_score = array_get_servers_rooted_sorted_by_score(ns);
    // iterate through array in reverse
    for (let integer_indices_0 = array_servers_rooted_sorted_by_score.length - 1; integer_indices_0 >= 0; --integer_indices_0) {
    const string_server_target = array_servers_rooted_sorted_by_score[integer_indices_0];
    if (ns.getHackingLevel() >= ns.getServerRequiredHackingLevel(string_server_target)) {
    return string_server_target;
    }
    }
    };
    const string_job_decider_prepare = function(ns, string_server_target, float_server_target_security, float_server_target_cash) {
    if (float_server_target_security > ns.getServerMinSecurityLevel(string_server_target)) {
    return "weaken";
    }
    if (float_server_target_cash < ns.getServerMaxMoney(string_server_target)) {
    return "grow";
    }
    return "";
    };
    const string_job_decider = function(ns, string_server_target, float_server_target_security, float_server_target_cash) {
    if (float_server_target_security > ns.getServerMinSecurityLevel(string_server_target)) {
    return "weaken";
    }
    else {
    if (float_server_target_cash < ns.getServerMaxMoney(string_server_target)) {
    return "grow";
    }
    else {
    return "hack";
    }
    }
    };
    const boolean_can_server_run_script_threads = function(ns, float_server_used_ram_free, float_script_ram, integer_threads) {
    if (float_script_ram * integer_threads > float_server_used_ram_free) {
    return false;
    }
    else {
    return true;
    }
    };
    // Returns time it takes to complete a hack on a server, in seconds. Adapted from `calculateHackingTime` in Hacking.js
    const float_get_time_hack = function(ns, string_server_target, float_server_target_security) {
    const object_constants = object_get_constants(ns);
    const difficultyMult = ns.getServerRequiredHackingLevel(string_server_target) * float_server_target_security;
    const baseDiff = 500;
    const baseSkill = 50;
    const diffFactor = 2.5;
    const intFactor = 0.1;
    const hack = object_constants.object_stats.hacking;
    const int = object_constants.object_stats.intelligence;
    var skillFactor = (diffFactor * difficultyMult + baseDiff);
    // tslint:disable-next-line
    skillFactor /= (hack + baseSkill + (intFactor * int));
    const hackTimeMultiplier = 5;
    const hackingTime = hackTimeMultiplier * skillFactor / object_constants.object_hacking_multipliers.speed;
    return hackingTime;
    };
    // Returns time it takes to complete a grow operation on a server, in seconds. Adapted from `calculateGrowTime` in Hacking.js
    const float_get_time_grow = function(ns, string_server_target, float_server_target_security) {
    const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
    return growTimeMultiplier * float_get_time_hack(ns, string_server_target, float_server_target_security);
    };
    // Returns time it takes to complete a weaken operation on a server, in seconds. Adapted from `calculateHackingTime` in Hacking.js
    const float_get_time_weaken = function(ns, string_server_target, float_server_target_security) {
    const weakenTimeMultiplier = 4; // Relative to hacking time
    return weakenTimeMultiplier * float_get_time_hack(ns, string_server_target, float_server_target_security);
    };
    // makes a schedule
    const array_make_schedule = function(ns, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target, string_decider) {
    const object_constants = object_get_constants(ns);
    const object_scripts = object_constants.object_scripts;
    const array_servers_rooted_sorted_by_ram = array_get_servers_rooted_sorted_by_ram(ns);
    const float_server_target_security_minimum = ns.getServerMinSecurityLevel(string_server_target);
    const float_server_target_cash_maximum = ns.getServerMaxMoney(string_server_target);
    const float_time_weaken = float_get_time_weaken(ns, string_server_target, ns.getServerSecurityLevel(string_server_target));
    const float_time_grow = float_get_time_grow(ns, string_server_target, ns.getServerSecurityLevel(string_server_target));
    const float_time_hack = float_get_time_hack(ns, string_server_target, ns.getServerSecurityLevel(string_server_target));
    // tripwires
    let boolean_end_loop_array_servers = false;
    let boolean_end_loop_server = false;
    let float_server_target_security_current = ns.getServerSecurityLevel(string_server_target);
    let float_server_target_cash_current = ns.getServerMoneyAvailable(string_server_target);
    let array_schedule = [];
    let integer_array_schedule_length = 0;
    // assumes weaken takes longest
    let integer_time_job_finishes_seconds = float_time_weaken;
    // iterate through servers in reverse to use servers with the biggest rams first
    for (let integer_indices_0 = array_servers_rooted_sorted_by_ram.length - 1; integer_indices_0 >= 0; --integer_indices_0) {
    if (integer_array_schedule_length >= integer_job_cap ||
    boolean_end_loop_array_servers) {
    break;
    }
    const string_server_used = array_servers_rooted_sorted_by_ram[integer_indices_0];
    let float_server_used_ram_free_current = float_get_server_ram_free(ns, string_server_used);
    while (
    float_server_used_ram_free_current > 0 &&
    integer_array_schedule_length < integer_job_cap &&
    !boolean_end_loop_array_servers &&
    !boolean_end_loop_server
    ) {
    const string_job = string_decider(ns, string_server_target, float_server_target_security_current, float_server_target_cash_current);
    const schedule_item = {
    string_job: string_job,
    string_server_used: string_server_used,
    string_server_target: string_server_target,
    float_server_target_security_before: float_server_target_security_current,
    float_server_target_cash_before: float_server_target_cash_current
    };
    switch (string_job) {
    case "": {
    boolean_end_loop_array_servers = true;
    break;
    }
    case "weaken": {
    if (!boolean_can_server_run_script_threads(ns, float_server_used_ram_free_current, object_scripts.weaken.ram, 1)) {
    // start using a server with more ram
    boolean_end_loop_server = true;
    break;
    }
    const integer_threads_weaken = integer_get_threads_weaken(ns, float_server_used_ram_free_current, string_server_target, float_server_target_security_current);
    float_server_used_ram_free_current -= integer_threads_weaken * object_scripts.weaken.ram;
    const float_server_target_security_uncorrected = float_server_target_security_current - float_get_security_decrease_from_weaken(ns, integer_threads_weaken);
    if (float_server_target_security_uncorrected < float_server_target_security_minimum) {
    float_server_target_security_current = float_server_target_security_minimum;
    }
    else {
    float_server_target_security_current = float_server_target_security_uncorrected;
    }
    schedule_item.float_server_target_security_current = float_server_target_security_current;
    schedule_item.float_delay_seconds = integer_time_job_finishes_seconds - float_time_weaken + float_padding_seconds;
    integer_time_job_finishes_seconds += float_padding_seconds;
    schedule_item.integer_time_job_finishes_seconds = integer_time_job_finishes_seconds;
    schedule_item.integer_threads = integer_threads_weaken;
    array_schedule.push(schedule_item);
    ++integer_array_schedule_length;
    break;
    }
    case "grow": {
    if (!boolean_can_server_run_script_threads(ns, float_server_used_ram_free_current, object_scripts.grow.ram, 1)) {
    // start using a server with more ram
    boolean_end_loop_server = true;
    break;
    }
    if (float_server_target_cash_current === 0) {
    float_server_target_cash_current = 1; // counts 0 cash as 1 so it can still grow. taken from `grow` in NetscriptFunctions.js
    }
    const integer_threads_grow = integer_get_threads_grow(ns, float_server_used_ram_free_current, string_server_target, float_server_target_security_current, float_server_target_cash_current);
    float_server_used_ram_free_current -= integer_threads_grow * object_scripts.grow.ram;
    const float_server_target_cash_current_uncorrected = float_server_target_cash_current * float_get_growth_from_threads(ns, string_server_target, float_server_target_security_current, integer_threads_grow);
    if (float_server_target_cash_current_uncorrected > float_server_target_cash_maximum) {
    float_server_target_cash_current = float_server_target_cash_maximum;
    }
    else {
    float_server_target_cash_current = float_server_target_cash_current_uncorrected;
    }
    // the following is adapted from `processSingleServerGrowth` in ServerHelpers.ts and `fortify` in Server.ts
    float_server_target_security_current += float_get_security_increase_from_grow(ns, integer_threads_grow);
    schedule_item.float_server_target_security_current = float_server_target_security_current;
    schedule_item.float_delay_seconds = integer_time_job_finishes_seconds - float_time_grow + float_padding_seconds;
    integer_time_job_finishes_seconds += float_padding_seconds;
    schedule_item.integer_time_job_finishes_seconds = integer_time_job_finishes_seconds;
    schedule_item.integer_threads = integer_threads_grow;
    array_schedule.push(schedule_item);
    ++integer_array_schedule_length;
    break;
    }
    case "hack": {
    if (!boolean_can_server_run_script_threads(ns, float_server_used_ram_free_current, object_scripts.hack.ram, 1)) {
    // start using a server with more ram
    boolean_end_loop_server = true;
    break;
    }
    const integer_threads_hack = integer_get_threads_hack(ns, float_server_used_ram_free_current, string_server_target, float_server_target_security_current, float_get_percentage_to_steal(ns, float_server_used_ram_free_current, string_server_target, float_server_target_cash_current, float_server_target_security_current, float_precision, float_steal_cap));
    float_server_used_ram_free_current -= integer_threads_hack * object_scripts.hack.ram;
    // the following is adapted from `hack` in NetscriptFunctions.js and `fortify` in Server.ts
    const float_server_target_cash_before = float_server_target_cash_current;
    const float_server_target_cash_current_uncorrected = float_server_target_cash_current - Math.floor(float_server_target_cash_current * float_get_percentage_of_cash_from_available_per_hack(ns, string_server_target, float_server_target_security_current)) * integer_threads_hack;
    if (float_server_target_cash_current_uncorrected < 0) {
    float_server_target_cash_current = 0;
    }
    else {
    float_server_target_cash_current = float_server_target_cash_current_uncorrected;
    }
    float_server_target_security_current += float_get_security_increase_from_hack(ns, string_server_target, float_server_target_security_current, float_server_target_cash_before, integer_threads_hack);
    schedule_item.float_server_target_security_current = float_server_target_security_current;
    schedule_item.float_delay_seconds = integer_time_job_finishes_seconds - float_time_hack + float_padding_seconds;
    integer_time_job_finishes_seconds += float_padding_seconds;
    schedule_item.integer_time_job_finishes_seconds = integer_time_job_finishes_seconds;
    schedule_item.integer_threads = integer_threads_hack;
    array_schedule.push(schedule_item);
    ++integer_array_schedule_length;
    break;
    }
    }
    }
    }
    // remove schedule items near the end that cause security to not equal minimum. in other words, the target should have minimum security when the cycle finishes. this is to make the next cycle of jobs run as quick as possible. TODO: make it so that we don't have to do this deleting step, instead, the array making steps above should already take into this into account and don't make more items than is needed.
    let array_schedule_edited = array_schedule;
    let boolean_have_not_seen_item_with_security_minimum = true;
    while (boolean_have_not_seen_item_with_security_minimum) {
    for (let integer_indices_1 = array_schedule_edited.length - 1; integer_indices_1 >= 0; --integer_indices_1) {
    if (!boolean_have_not_seen_item_with_security_minimum) {
    break;
    }
    const object_job = array_schedule_edited[integer_indices_1];
    if (object_job.float_server_target_security_current === float_server_target_security_minimum) {
    boolean_have_not_seen_item_with_security_minimum = false;
    break;
    }
    else {
    array_schedule_edited.splice(integer_indices_1, 1);
    }
    }
    }
    if (boolean_have_not_seen_item_with_security_minimum) {
    return array_schedule;
    }
    else {
    return array_schedule_edited;
    }
    };
    const void_schedule_runner = async function(ns, array_schedule) {
    for (let integer_indices_0 = 0; integer_indices_0 < array_schedule.length; ++integer_indices_0) {
    const string_job = array_schedule[integer_indices_0].string_job;
    const string_server_used = array_schedule[integer_indices_0].string_server_used;
    const string_server_target = array_schedule[integer_indices_0].string_server_target;
    const integer_threads = array_schedule[integer_indices_0].integer_threads;
    const float_delay = array_schedule[integer_indices_0].float_delay_seconds * 1000;
    const identifier = integer_indices_0;
    let string_script = "";
    switch (string_job) {
    case "weaken": {
    string_script = object_get_constants(ns).object_scripts.weaken.file;
    break;
    }
    case "grow": {
    string_script = object_get_constants(ns).object_scripts.grow.file;
    break;
    }
    case "hack": {
    string_script = object_get_constants(ns).object_scripts.hack.file;
    break;
    }
    }
    await ns.exec(string_script, string_server_used, integer_threads, string_server_used, string_server_target, float_delay, identifier);
    }
    };
    const boolean_script_running = function(ns, string_script) {
    const array_servers = array_get_servers(ns);
    for (let integer_indices_0 = 0; integer_indices_0 < array_servers.length; ++integer_indices_0) {
    const string_server = array_servers[integer_indices_0];
    const array_scripts_running = ns.ps(string_server);
    if (array_scripts_running.length > 0) {
    for (let integer_indices_1 = 0; integer_indices_1 < array_scripts_running.length; ++integer_indices_1) {
    const object_script = array_scripts_running[integer_indices_1];
    const string_script_to_check = object_script.filename;
    if (string_script_to_check == string_script) {
    return true;
    }
    }
    }
    }
    return false;
    };
    const void_script_executor = async function(ns, array_scripts) {
    const array_servers_rooted_sorted_by_ram = array_get_servers_rooted_sorted_by_ram(ns);
    for (let integer_indices_0 = 0; integer_indices_0 < array_scripts.length; ++integer_indices_0) {
    const object_script = array_scripts[integer_indices_0];
    const string_path = object_script.file;
    const float_ram = object_script.ram;
    const integer_threads = object_script.threads;
    const array_arguments = object_script.arguments;
    if (!boolean_script_running(ns, string_path)) {
    // use servers with the biggest rams first
    for (let integer_indices_0 = array_servers_rooted_sorted_by_ram.length - 1; integer_indices_0 >= 0; --integer_indices_0) {
    const string_server_used = array_servers_rooted_sorted_by_ram[integer_indices_0];
    let float_server_used_ram_free_current = float_get_server_ram_free(ns, string_server_used);
    if (float_server_used_ram_free_current >= float_ram * integer_threads) {
    try {
    await ns.exec(string_path, string_server_used, integer_threads, ...array_arguments);
    } catch (error) {
    ns.tprint(JSON.stringify(error));
    }
    break;
    }
    }
    }
    }
    };
    // returns the the time it'll take to finish in milliseconds.
    export const void_runner = async function(ns, string_servers_bought_name, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target_argument, float_period_check_seconds) {
    const object_constants = object_get_constants(ns);
    const object_scripts = object_constants.object_scripts;
    let string_server_target = string_server_target_argument;
    if (string_server_target_argument === "") {
    string_server_target = string_get_server_rooted_hackable_with_score_biggest(ns);
    }
    // should probably merge this into constants?
    const array_scripts = [
    // // uncomment if you have source-file 4
    // {
    // file: "ram.js",
    // ram: 6.2,
    // threads: 1,
    // arguments: [float_period_check_seconds]
    // },
    {
    file: "servers.js",
    ram: 8.55,
    threads: 1,
    arguments: [float_period_check_seconds, string_servers_bought_name]
    },
    {
    file: "botnet.js",
    ram: 2.15,
    threads: 1,
    arguments: [float_period_check_seconds]
    }
    ];
    await void_script_executor(ns, array_scripts);
    // copy object_scripts to rooted servers
    void_copy_files_to_string_servers_rooted(ns, [
    object_scripts.weaken.file,
    object_scripts.grow.file,
    object_scripts.hack.file
    ], object_constants.string_host);
    // prepare the target if necessary
    while (true) {
    if (
    ns.getServerSecurityLevel(string_server_target) === ns.getServerMinSecurityLevel(string_server_target) &&
    ns.getServerMoneyAvailable(string_server_target) === ns.getServerMaxMoney(string_server_target)
    ) {
    break;
    }
    const array_schedule_prepare = array_make_schedule(ns, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target, string_job_decider_prepare);
    if (array_schedule_prepare.length > 0) {
    await void_schedule_runner(ns, array_schedule_prepare);
    await ns.sleep(array_schedule_prepare[array_schedule_prepare.length - 1].integer_time_job_finishes_seconds * 1000);
    }
    }
    // make and run actual hacking schedule
    const array_schedule = array_make_schedule(ns, integer_job_cap, float_precision, float_steal_cap, float_padding_seconds, string_server_target, string_job_decider);
    await void_schedule_runner(ns, array_schedule);
    return array_schedule[array_schedule.length - 1].integer_time_job_finishes_seconds * 1000;
  • replacement in README.md at line 8
    [5.3110][5.3110:3288]()
    Here's an overview of what the executable scripts (located in the `bin` directory of this repository) are supposed to do, as well as usage information and examples for each one:
    [5.3110]
    [5.3288]
    Here's an overview of what the executable scripts (located in the "bin" directory of this repository) are supposed to do, as well as usage information and examples for each one:
  • replacement in README.md at line 10
    [5.3289][5.3289:3314](),[5.3314][5.3118:3446](),[5.3118][5.3118:3446](),[5.3446][4.1586:1624]()
    ### `main.js` (15.70 GB)
    * Buy and replace old servers whenever appropriate.
    * Try to exploit and root servers if possible.
    * Copy `weaken.js`, `grow.js` and `hack.js` scripts to other servers.
    * Make a schedule containing information about when, where and how many threads (among other information) each of the scripts should be executed with.
    * Execute the jobs in the schedule.
    [5.3289]
    [5.3487]
    ### "main.js" (9.10 [+6.2] [+8.55] [+2.15] GB)
    * Run helper scripts that should:
    * Upgrade your home server's RAM (you need to uncomment some code and have SF-4).
    * Buy and replace old servers whenever appropriate.
    * Try to exploit and root servers if possible.
    * Copy the "weaken.js", "grow.js" and "hack.js" worker scripts to other servers.
    * Make and execute a "preparation" schedule containing information about when, where and how many threads (among other information) the "weaken.js" and "grow.js" should be executed with.
    * Make and execute a "hacking" schedule containing information about when, where and how many threads (among other information) all three of the worker scripts should be executed with.
  • replacement in README.md at line 63
    [5.5169][5.5169:5196]()
    ### `killall.js` (3.05 GB)
    [5.5169]
    [5.3528]
    ### "killall.js" (3.05 GB)
  • replacement in README.md at line 79
    [5.5552][5.5552:5576]()
    ### `lshw.js` (2.45 GB)
    [5.5552]
    [5.3600]
    ### "lshw.js" (2.45 GB)
  • replacement in README.md at line 100
    [5.3873390][5.6197:6219]()
    ### `cp.js` (2.65 GB)
    [5.3873390]
    [5.3004]
    ### "cp.js" (2.65 GB)