NETSCRIPT: add formulas.hacking.growAmount() (#1090)

Also, improve docs.
This commit is contained in:
David Walker 2024-03-26 03:26:50 -07:00 committed by GitHub
parent d8de22a273
commit 75dabd10be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 132 additions and 32 deletions

@ -0,0 +1,33 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [HackingFormulas](./bitburner.hackingformulas.md) &gt; [growAmount](./bitburner.hackingformulas.growamount.md)
## HackingFormulas.growAmount() method
Calculate the amount of money a grow action will leave a server with. Starting money is server.moneyAvailable. Note that when simulating the effect of [grow](./bitburner.ns.grow.md)<!-- -->, what matters is the state of the server and player when the grow \*finishes\*, not when it is started.
The growth amount depends both linearly \*and\* exponentially on threads; see [grow](./bitburner.ns.grow.md) for more details.
The inverse of this function is [formulas.hacking.growThreads](./bitburner.hackingformulas.growthreads.md)<!-- -->, although it rounds up to integer threads.
**Signature:**
```typescript
growAmount(server: Server, player: Person, threads: number, cores?: number): number;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| server | [Server](./bitburner.server.md) | Server info, typically from [getServer](./bitburner.ns.getserver.md) |
| player | [Person](./bitburner.person.md) | Player info, typically from [getPlayer](./bitburner.ns.getplayer.md) |
| threads | number | Number of threads to grow with. Can be fractional. |
| cores | number | _(Optional)_ Number of cores on the computer that will execute grow. |
**Returns:**
number
The amount of money after the calculated grow.

@ -4,7 +4,13 @@
## HackingFormulas.growPercent() method ## HackingFormulas.growPercent() method
Calculate the percent a server would grow to. Not exact due to limitations of mathematics. (Ex: 3.0 would grow the server to 300% of its current value.) Calculate the growth multiplier constant for a given server and threads.
The actual amount of money grown depends both linearly \*and\* exponentially on threads; this is only giving the exponential part that is used for the multiplier. See [grow](./bitburner.ns.grow.md) for more details.
As a result of the above, this multiplier does \*not\* depend on the amount of money on the server. Changing server.moneyAvailable and server.moneyMax will have no effect.
For the most common use-cases, you probably want either [formulas.hacking.growThreads](./bitburner.hackingformulas.growthreads.md) or [formulas.hacking.growAmount](./bitburner.hackingformulas.growamount.md) instead.
**Signature:** **Signature:**
@ -17,7 +23,7 @@ growPercent(server: Server, threads: number, player: Person, cores?: number): nu
| Parameter | Type | Description | | Parameter | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| server | [Server](./bitburner.server.md) | Server info, typically from [getServer](./bitburner.ns.getserver.md) | | server | [Server](./bitburner.server.md) | Server info, typically from [getServer](./bitburner.ns.getserver.md) |
| threads | number | Amount of thread. | | threads | number | Amount of threads. Can be fractional. |
| player | [Person](./bitburner.person.md) | Player info, typically from [getPlayer](./bitburner.ns.getplayer.md) | | player | [Person](./bitburner.person.md) | Player info, typically from [getPlayer](./bitburner.ns.getplayer.md) |
| cores | number | _(Optional)_ Number of cores on the computer that will execute grow. | | cores | number | _(Optional)_ Number of cores on the computer that will execute grow. |

@ -4,7 +4,11 @@
## HackingFormulas.growThreads() method ## HackingFormulas.growThreads() method
Calculate how many threads it will take to grow server to targetMoney. Starting money is server.moneyAvailable. Calculate how many threads it will take to grow server to targetMoney. Starting money is server.moneyAvailable. Note that when simulating the effect of [grow](./bitburner.ns.grow.md)<!-- -->, what matters is the state of the server and player when the grow \*finishes\*, not when it is started.
The growth amount depends both linearly \*and\* exponentially on threads; see [grow](./bitburner.ns.grow.md) for more details.
The inverse of this function is [formulas.hacking.growAmount](./bitburner.hackingformulas.growamount.md)<!-- -->, although it can work with fractional threads.
**Signature:** **Signature:**

@ -16,8 +16,9 @@ interface HackingFormulas
| Method | Description | | Method | Description |
| --- | --- | | --- | --- |
| [growPercent(server, threads, player, cores)](./bitburner.hackingformulas.growpercent.md) | Calculate the percent a server would grow to. Not exact due to limitations of mathematics. (Ex: 3.0 would grow the server to 300% of its current value.) | | [growAmount(server, player, threads, cores)](./bitburner.hackingformulas.growamount.md) | <p>Calculate the amount of money a grow action will leave a server with. Starting money is server.moneyAvailable. Note that when simulating the effect of [grow](./bitburner.ns.grow.md)<!-- -->, what matters is the state of the server and player when the grow \*finishes\*, not when it is started.</p><p>The growth amount depends both linearly \*and\* exponentially on threads; see [grow](./bitburner.ns.grow.md) for more details.</p><p>The inverse of this function is [formulas.hacking.growThreads](./bitburner.hackingformulas.growthreads.md)<!-- -->, although it rounds up to integer threads.</p> |
| [growThreads(server, player, targetMoney, cores)](./bitburner.hackingformulas.growthreads.md) | Calculate how many threads it will take to grow server to targetMoney. Starting money is server.moneyAvailable. | | [growPercent(server, threads, player, cores)](./bitburner.hackingformulas.growpercent.md) | <p>Calculate the growth multiplier constant for a given server and threads.</p><p>The actual amount of money grown depends both linearly \*and\* exponentially on threads; this is only giving the exponential part that is used for the multiplier. See [grow](./bitburner.ns.grow.md) for more details.</p><p>As a result of the above, this multiplier does \*not\* depend on the amount of money on the server. Changing server.moneyAvailable and server.moneyMax will have no effect.</p><p>For the most common use-cases, you probably want either [formulas.hacking.growThreads](./bitburner.hackingformulas.growthreads.md) or [formulas.hacking.growAmount](./bitburner.hackingformulas.growamount.md) instead.</p> |
| [growThreads(server, player, targetMoney, cores)](./bitburner.hackingformulas.growthreads.md) | <p>Calculate how many threads it will take to grow server to targetMoney. Starting money is server.moneyAvailable. Note that when simulating the effect of [grow](./bitburner.ns.grow.md)<!-- -->, what matters is the state of the server and player when the grow \*finishes\*, not when it is started.</p><p>The growth amount depends both linearly \*and\* exponentially on threads; see [grow](./bitburner.ns.grow.md) for more details.</p><p>The inverse of this function is [formulas.hacking.growAmount](./bitburner.hackingformulas.growamount.md)<!-- -->, although it can work with fractional threads.</p> |
| [growTime(server, player)](./bitburner.hackingformulas.growtime.md) | Calculate grow time. | | [growTime(server, player)](./bitburner.hackingformulas.growtime.md) | Calculate grow time. |
| [hackChance(server, player)](./bitburner.hackingformulas.hackchance.md) | Calculate hack chance. (Ex: 0.25 would indicate a 25% chance of success.) | | [hackChance(server, player)](./bitburner.hackingformulas.hackchance.md) | Calculate hack chance. (Ex: 0.25 would indicate a 25% chance of success.) |
| [hackExp(server, player)](./bitburner.hackingformulas.hackexp.md) | Calculate hack exp for one thread. | | [hackExp(server, player)](./bitburner.hackingformulas.hackexp.md) | Calculate hack exp for one thread. |

@ -41,7 +41,9 @@ The multiplier scales exponentially with thread count, and its base depends on t
[growthAnalyze](./bitburner.ns.growthanalyze.md) can be used to determine the number of threads needed for a specified multiplicative portion of server growth. [growthAnalyze](./bitburner.ns.growthanalyze.md) can be used to determine the number of threads needed for a specified multiplicative portion of server growth.
To determine the effect of a single grow, obtain access to the Formulas API and use [formulas.hacking.growPercent](./bitburner.hackingformulas.growpercent.md)<!-- -->, or invert [growthAnalyze](./bitburner.ns.growthanalyze.md)<!-- -->. To determine the effect of a single grow, obtain access to the Formulas API and use [formulas.hacking.growPercent](./bitburner.hackingformulas.growamount.md)<!-- -->, or invert [growthAnalyze](./bitburner.ns.growthanalyze.md)<!-- -->.
To determine how many threads are needed to return a server to max money, obtain access to the Formulas API and use [formulas.hacking.growThreads](./bitburner.hackingformulas.growthreads.md)<!-- -->, or [NS.growthAnalyze()](./bitburner.ns.growthanalyze.md) \*if\* the server will be at the same security in the future.
Like [hack](./bitburner.ns.hack.md)<!-- -->, `grow` can be called on any hackable server, regardless of where the script is running. Hackable servers are any servers not owned by the player. Like [hack](./bitburner.ns.hack.md)<!-- -->, `grow` can be called on any hackable server, regardless of where the script is running. Hackable servers are any servers not owned by the player.

@ -615,6 +615,7 @@ export const RamCosts: RamCostTree<NSFull> = {
hackPercent: 0, hackPercent: 0,
growPercent: 0, growPercent: 0,
growThreads: 0, growThreads: 0,
growAmount: 0,
hackTime: 0, hackTime: 0,
growTime: 0, growTime: 0,
weakenTime: 0, weakenTime: 0,

@ -1,5 +1,5 @@
import { Player as player } from "../Player"; import { Player as player } from "../Player";
import { calculateServerGrowth } from "../Server/formulas/grow"; import { calculateServerGrowth, calculateGrowMoney } from "../Server/formulas/grow";
import { numCycleForGrowthCorrected } from "../Server/ServerHelpers"; import { numCycleForGrowthCorrected } from "../Server/ServerHelpers";
import { import {
calculateMoneyGainRate, calculateMoneyGainRate,
@ -196,6 +196,16 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
checkFormulasAccess(ctx); checkFormulasAccess(ctx);
return numCycleForGrowthCorrected(server, targetMoney, startMoney, cores, player); return numCycleForGrowthCorrected(server, targetMoney, startMoney, cores, player);
}, },
growAmount:
(ctx) =>
(_server, _player, _threads, _cores = 1) => {
const server = helpers.server(ctx, _server);
const person = helpers.person(ctx, _player);
const threads = helpers.number(ctx, "threads", _threads);
const cores = helpers.number(ctx, "cores", _cores);
checkFormulasAccess(ctx);
return calculateGrowMoney(server, threads, person, cores);
},
hackTime: (ctx) => (_server, _player) => { hackTime: (ctx) => (_server, _player) => {
const server = helpers.server(ctx, _server); const server = helpers.server(ctx, _server);
const person = helpers.person(ctx, _player); const person = helpers.person(ctx, _player);

@ -4684,11 +4684,20 @@ interface HackingFormulas {
*/ */
hackPercent(server: Server, player: Person): number; hackPercent(server: Server, player: Person): number;
/** /**
* Calculate the percent a server would grow to. * Calculate the growth multiplier constant for a given server and threads.
* Not exact due to limitations of mathematics. *
* (Ex: 3.0 would grow the server to 300% of its current value.) * The actual amount of money grown depends both linearly *and* exponentially on threads;
* this is only giving the exponential part that is used for the multiplier.
* See {@link NS.grow | grow} for more details.
*
* As a result of the above, this multiplier does *not* depend on the amount of money on the server.
* Changing server.moneyAvailable and server.moneyMax will have no effect.
*
* For the most common use-cases, you probably want
* either {@link HackingFormulas.growThreads | formulas.hacking.growThreads}
* or {@link HackingFormulas.growAmount | formulas.hacking.growAmount} instead.
* @param server - Server info, typically from {@link NS.getServer | getServer} * @param server - Server info, typically from {@link NS.getServer | getServer}
* @param threads - Amount of thread. * @param threads - Amount of threads. Can be fractional.
* @param player - Player info, typically from {@link NS.getPlayer | getPlayer} * @param player - Player info, typically from {@link NS.getPlayer | getPlayer}
* @param cores - Number of cores on the computer that will execute grow. * @param cores - Number of cores on the computer that will execute grow.
* @returns The calculated grow percent. * @returns The calculated grow percent.
@ -4696,6 +4705,13 @@ interface HackingFormulas {
growPercent(server: Server, threads: number, player: Person, cores?: number): number; growPercent(server: Server, threads: number, player: Person, cores?: number): number;
/** /**
* Calculate how many threads it will take to grow server to targetMoney. Starting money is server.moneyAvailable. * Calculate how many threads it will take to grow server to targetMoney. Starting money is server.moneyAvailable.
* Note that when simulating the effect of {@link NS.grow | grow}, what matters is the state of the server and player
* when the grow *finishes*, not when it is started.
*
* The growth amount depends both linearly *and* exponentially on threads; see {@link NS.grow | grow} for more details.
*
* The inverse of this function is {@link HackingFormulas.growAmount | formulas.hacking.growAmount},
* although it can work with fractional threads.
* @param server - Server info, typically from {@link NS.getServer | getServer} * @param server - Server info, typically from {@link NS.getServer | getServer}
* @param player - Player info, typically from {@link NS.getPlayer | getPlayer} * @param player - Player info, typically from {@link NS.getPlayer | getPlayer}
* @param targetMoney - Desired final money, capped to server's moneyMax * @param targetMoney - Desired final money, capped to server's moneyMax
@ -4703,6 +4719,22 @@ interface HackingFormulas {
* @returns The calculated grow threads as an integer, rounded up. * @returns The calculated grow threads as an integer, rounded up.
*/ */
growThreads(server: Server, player: Person, targetMoney: number, cores?: number): number; growThreads(server: Server, player: Person, targetMoney: number, cores?: number): number;
/**
* Calculate the amount of money a grow action will leave a server with. Starting money is server.moneyAvailable.
* Note that when simulating the effect of {@link NS.grow | grow}, what matters is the state of the server and player
* when the grow *finishes*, not when it is started.
*
* The growth amount depends both linearly *and* exponentially on threads; see {@link NS.grow | grow} for more details.
*
* The inverse of this function is {@link HackingFormulas.growThreads | formulas.hacking.growThreads},
* although it rounds up to integer threads.
* @param server - Server info, typically from {@link NS.getServer | getServer}
* @param player - Player info, typically from {@link NS.getPlayer | getPlayer}
* @param threads - Number of threads to grow with. Can be fractional.
* @param cores - Number of cores on the computer that will execute grow.
* @returns The amount of money after the calculated grow.
*/
growAmount(server: Server, player: Person, threads: number, cores?: number): number;
/** /**
* Calculate hack time. * Calculate hack time.
* @param server - Server info, typically from {@link NS.getServer | getServer} * @param server - Server info, typically from {@link NS.getServer | getServer}
@ -5365,7 +5397,11 @@ export interface NS {
* multiplicative portion of server growth. * multiplicative portion of server growth.
* *
* To determine the effect of a single grow, obtain access to the Formulas API and use * To determine the effect of a single grow, obtain access to the Formulas API and use
* {@link HackingFormulas.growPercent | formulas.hacking.growPercent}, or invert {@link NS.growthAnalyze | growthAnalyze}. * {@link HackingFormulas.growAmount | formulas.hacking.growPercent}, or invert {@link NS.growthAnalyze | growthAnalyze}.
*
* To determine how many threads are needed to return a server to max money, obtain access to the Formulas API and use
* {@link HackingFormulas.growThreads | formulas.hacking.growThreads}, or {@link NS.growthAnalyze} *if* the server will
* be at the same security in the future.
* *
* Like {@link NS.hack | hack}, `grow` can be called on any hackable server, regardless of where the script is * Like {@link NS.hack | hack}, `grow` can be called on any hackable server, regardless of where the script is
* running. Hackable servers are any servers not owned by the player. * running. Hackable servers are any servers not owned by the player.

@ -1,13 +1,12 @@
import { GetServer, createUniqueRandomIp, ipExists } from "./AllServers"; import { GetServer, createUniqueRandomIp, ipExists } from "./AllServers";
import { Server, IConstructorParams } from "./Server"; import { Server, IConstructorParams } from "./Server";
import { BaseServer } from "./BaseServer"; import { BaseServer } from "./BaseServer";
import { calculateServerGrowth, calculateServerGrowthLog } from "./formulas/grow"; import { calculateGrowMoney, calculateServerGrowthLog } from "./formulas/grow";
import { currentNodeMults } from "../BitNode/BitNodeMultipliers"; import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
import { ServerConstants } from "./data/Constants"; import { ServerConstants } from "./data/Constants";
import { Player } from "@player"; import { Player } from "@player";
import { CompletedProgramName, LiteratureName } from "@enums"; import { CompletedProgramName, LiteratureName } from "@enums";
import { Person as IPerson } from "@nsdefs"; import { Person as IPerson } from "@nsdefs";
import { isValidNumber } from "../utils/helpers/isValidNumber";
import { Server as IServer } from "@nsdefs"; import { Server as IServer } from "@nsdefs";
import { workerScripts } from "../Netscript/WorkerScripts"; import { workerScripts } from "../Netscript/WorkerScripts";
import { killWorkerScriptByPid } from "../Netscript/killWorkerScript"; import { killWorkerScriptByPid } from "../Netscript/killWorkerScript";
@ -177,25 +176,8 @@ export function numCycleForGrowthCorrected(
//Applied server growth for a single server. Returns the percentage growth //Applied server growth for a single server. Returns the percentage growth
export function processSingleServerGrowth(server: Server, threads: number, cores = 1): number { export function processSingleServerGrowth(server: Server, threads: number, cores = 1): number {
let serverGrowth = calculateServerGrowth(server, threads, Player, cores);
if (serverGrowth < 1) {
console.warn("serverGrowth calculated to be less than 1");
serverGrowth = 1;
}
const oldMoneyAvailable = server.moneyAvailable; const oldMoneyAvailable = server.moneyAvailable;
server.moneyAvailable += threads; // It can be grown even if it has no money server.moneyAvailable = calculateGrowMoney(server, threads, Player, cores);
server.moneyAvailable *= serverGrowth;
// in case of data corruption
if (isValidNumber(server.moneyMax) && isNaN(server.moneyAvailable)) {
server.moneyAvailable = server.moneyMax;
}
// cap at max
if (isValidNumber(server.moneyMax) && server.moneyAvailable > server.moneyMax) {
server.moneyAvailable = server.moneyMax;
}
// if there was any growth at all, increase security // if there was any growth at all, increase security
if (oldMoneyAvailable !== server.moneyAvailable) { if (oldMoneyAvailable !== server.moneyAvailable) {

@ -1,6 +1,7 @@
import { currentNodeMults } from "../../BitNode/BitNodeMultipliers"; import { currentNodeMults } from "../../BitNode/BitNodeMultipliers";
import { Person as IPerson, Server as IServer } from "@nsdefs"; import { Person as IPerson, Server as IServer } from "@nsdefs";
import { ServerConstants } from "../data/Constants"; import { ServerConstants } from "../data/Constants";
import { isValidNumber } from "../../utils/helpers/isValidNumber";
// Returns the log of the growth rate. When passing 1 for threads, this gives a useful constant. // Returns the log of the growth rate. When passing 1 for threads, this gives a useful constant.
export function calculateServerGrowthLog(server: IServer, threads: number, p: IPerson, cores = 1): number { export function calculateServerGrowthLog(server: IServer, threads: number, p: IPerson, cores = 1): number {
@ -30,3 +31,27 @@ export function calculateServerGrowth(server: IServer, threads: number, p: IPers
if (!server.serverGrowth) return 0; if (!server.serverGrowth) return 0;
return Math.exp(calculateServerGrowthLog(server, threads, p, cores)); return Math.exp(calculateServerGrowthLog(server, threads, p, cores));
} }
// This differs from calculateServerGrowth in that it includes the additive
// factor and all the boundary checks.
export function calculateGrowMoney(server: IServer, threads: number, p: IPerson, cores = 1): number {
let serverGrowth = calculateServerGrowth(server, threads, p, cores);
if (serverGrowth < 1) {
console.warn("serverGrowth calculated to be less than 1");
serverGrowth = 1;
}
let moneyAvailable = server.moneyAvailable ?? Number.NaN;
moneyAvailable += threads; // It can be grown even if it has no money
moneyAvailable *= serverGrowth;
// cap at max (or data corruption)
if (
server.moneyMax !== undefined &&
isValidNumber(server.moneyMax) &&
(moneyAvailable > server.moneyMax || isNaN(moneyAvailable))
) {
moneyAvailable = server.moneyMax;
}
return moneyAvailable;
}