Fixed documentation typos in v0.47.0

This commit is contained in:
danielyxie 2019-05-17 15:51:28 -07:00
parent 95c928afc9
commit a2551f98c2
8 changed files with 117 additions and 79 deletions

@ -16,8 +16,6 @@ You can use the Singularity Functions in other BitNodes if and only if you have
Source-File 4 will open up additional Singularity Functions that you can use in other BitNodes. If your Source-File 4 is upgraded all the way to
level 3, then you will be able to access all of the Singularity Functions.
Note that Singularity Functions require twice as much RAM outside of BitNode-4
.. toctree::
:caption: Functions:

@ -4,7 +4,7 @@ getStockSaleGain() Netscript Function
.. js:function:: getStockSaleGain(sym, shares, posType)
:param string sym: Stock symbol
:param number shares: Number of shares to purchase
:param number shares: Number of shares to sell
:param string posType: Specifies whether the order is a "Long" or "Short" position.
The values "L" or "S" can also be used.
:RAM cost: 2 GB

@ -1,3 +1,13 @@
/**
* Generic helper/utility functions for the Hacknet mechanic:
* - Purchase nodes/upgrades
* - Calculating maximum number of upgrades
* - Processing Hacknet earnings
* - Updating Hash Manager capacity
* - Purchasing hash upgrades
*
* TODO Should probably split the different types of functions into their own modules
*/
import {
HacknetNode,
BaseCostForHacknetNode,
@ -26,7 +36,7 @@ import {
ITutorial
} from "../InteractiveTutorial";
import { Player } from "../Player";
import { AddToAllServers, AllServers } from "../Server/AllServers";
import { AllServers } from "../Server/AllServers";
import { GetServerByHostname } from "../Server/ServerHelpers";
import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
import { Page, routing } from "../ui/navigationTracking";
@ -115,7 +125,7 @@ export function getCostOfNextHacknetServer() {
return BaseCostForHacknetServer * Math.pow(mult, numOwned) * Player.hacknet_node_purchase_cost_mult;
}
//Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's level
export function getMaxNumberLevelUpgrades(nodeObj, maxLevel) {
if (maxLevel == null) {
throw new Error(`getMaxNumberLevelUpgrades() called without maxLevel arg`);
@ -149,6 +159,7 @@ export function getMaxNumberLevelUpgrades(nodeObj, maxLevel) {
return 0;
}
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's RAM
export function getMaxNumberRamUpgrades(nodeObj, maxLevel) {
if (maxLevel == null) {
throw new Error(`getMaxNumberRamUpgrades() called without maxLevel arg`);
@ -177,6 +188,7 @@ export function getMaxNumberRamUpgrades(nodeObj, maxLevel) {
return 0;
}
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's cores
export function getMaxNumberCoreUpgrades(nodeObj, maxLevel) {
if (maxLevel == null) {
throw new Error(`getMaxNumberCoreUpgrades() called without maxLevel arg`);
@ -212,6 +224,7 @@ export function getMaxNumberCoreUpgrades(nodeObj, maxLevel) {
return 0;
}
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's cache
export function getMaxNumberCacheUpgrades(nodeObj, maxLevel) {
if (maxLevel == null) {
throw new Error(`getMaxNumberCacheUpgrades() called without maxLevel arg`);

@ -176,33 +176,28 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
return totalCost;
}
// Process this Hacknet Server in the game loop.
// Returns the number of hashes generated
// Process this Hacknet Server in the game loop. Returns the number of hashes generated
process(numCycles: number=1): number {
const seconds = numCycles * CONSTANTS.MilliPerCycle / 1000;
return this.hashRate * seconds;
}
// Returns a boolean indicating whether the cache was successfully upgraded
upgradeCache(levels: number): void {
this.cache = Math.min(HacknetServerMaxCache, Math.round(this.cache + levels));
this.updateHashCapacity();
}
// Returns a boolean indicating whether the number of cores was successfully upgraded
upgradeCore(levels: number, prodMult: number): void {
this.cores = Math.min(HacknetServerMaxCores, Math.round(this.cores + levels));
this.updateHashRate(prodMult);
}
// Returns a boolean indicating whether the level was successfully upgraded
upgradeLevel(levels: number, prodMult: number): void {
this.level = Math.min(HacknetServerMaxLevel, Math.round(this.level + levels));
this.updateHashRate(prodMult);
}
// Returns a boolean indicating whether the RAM was successfully upgraded
upgradeRam(levels: number, prodMult: number): boolean {
for (let i = 0; i < levels; ++i) {
this.maxRam *= 2;
@ -213,9 +208,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
return true;
}
/**
* Whenever a script is run, we must update this server's hash rate
*/
// Whenever a script is run, we must update this server's hash rate
runScript(script: RunningScript, prodMult?: number): void {
super.runScript(script);
if (prodMult != null && typeof prodMult === "number") {

@ -40,13 +40,15 @@ import { createPopupCloseButton } from "../../utils/uiHelpers/createPopupCloseBu
import { removeElementById } from "../../utils/uiHelpers/removeElementById";
/**
* Create a pop-up box that lets the player confirm traveling to a different city
* If settings are configured to suppress this popup, just instantly travel
* Create a pop-up box that lets the player confirm traveling to a different city.
* If settings are configured to suppress this popup, just instantly travel.
* The actual "Travel" implementation is implemented in the UI, and is passed in
* as an argument
* as an argument.
* @param {CityName} destination - City that the player is traveling to
* @param {Function} travelFn - Function that changes the player's state for traveling
*/
type TravelFunction = (to: CityName) => void;
export function createTravelPopup(destination: CityName, travelFn: TravelFunction) {
export function createTravelPopup(destination: CityName, travelFn: TravelFunction): void {
const cost = CONSTANTS.TravelCost;
if (Settings.SuppressTravelConfirmation) {
@ -80,10 +82,10 @@ export function createTravelPopup(destination: CityName, travelFn: TravelFunctio
/**
* Create a pop-up box that lets the player purchase a server.
* @param ram - Amount of RAM (GB) on server
* @param p - Player object
* @param {number} ram - Amount of RAM (GB) on server
* @param {IPlayer} p - Player object
*/
export function createPurchaseServerPopup(ram: number, p: IPlayer) {
export function createPurchaseServerPopup(ram: number, p: IPlayer): void {
const cost = getPurchaseServerCost(ram);
if (cost === Infinity) {
dialogBoxCreate("Something went wrong when trying to purchase this server. Please contact developer");
@ -111,6 +113,7 @@ export function createPurchaseServerPopup(ram: number, p: IPlayer) {
/**
* Create a popup that lets the player start a Corporation
* @param {IPlayer} p - Player object
*/
export function createStartCorporationPopup(p: IPlayer) {
if (!p.canAccessCorporation() || p.hasCorporation()) { return; }
@ -172,8 +175,10 @@ export function createStartCorporationPopup(p: IPlayer) {
if (worldHeader instanceof HTMLElement) {
worldHeader.click(); worldHeader.click();
}
dialogBoxCreate("Congratulations! You just started your own corporation with government seed money. " +
"You can visit and manage your company in the City");
dialogBoxCreate(
"Congratulations! You just started your own corporation with government seed money. " +
"You can visit and manage your company in the City"
);
removeElementById(popupId);
return false;
}
@ -187,21 +192,23 @@ export function createStartCorporationPopup(p: IPlayer) {
/**
* Create a popup that lets the player upgrade the cores on his/her home computer
* @param p - Player object
* @param {IPlayer} p - Player object
*/
export function createUpgradeHomeCoresPopup(p: IPlayer) {
const currentCores = p.getHomeComputer().cpuCores;
if (currentCores >= 8) { return; } // Max of 8 cores
// Cost of purchasing another cost is found by indexing this array with number of current cores
const allCosts = [0,
10e9, // 1->2 Cores - 10 bn
250e9, // 2->3 Cores - 250 bn
5e12, // 3->4 Cores - 5 trillion
100e12, // 4->5 Cores - 100 trillion
1e15, // 5->6 Cores - 1 quadrillion
20e15, // 6->7 Cores - 20 quadrillion
200e15]; // 7->8 Cores - 200 quadrillion
const allCosts = [
0,
10e9,
250e9,
5e12,
100e12,
1e15,
20e15,
200e15
];
const cost: number = allCosts[currentCores];
const yesBtn = yesNoBoxGetYesButton();
@ -215,8 +222,10 @@ export function createUpgradeHomeCoresPopup(p: IPlayer) {
} else {
p.loseMoney(cost);
p.getHomeComputer().cpuCores++;
dialogBoxCreate("You purchased an additional CPU Core for your home computer! It now has " +
p.getHomeComputer().cpuCores + " cores.");
dialogBoxCreate(
"You purchased an additional CPU Core for your home computer! It now has " +
p.getHomeComputer().cpuCores + " cores."
);
}
yesNoBoxClose();
});
@ -226,15 +235,17 @@ export function createUpgradeHomeCoresPopup(p: IPlayer) {
yesNoBoxClose();
});
yesNoBoxCreate("Would you like to purchase an additional CPU Core for your home computer? Each CPU Core " +
yesNoBoxCreate(
"Would you like to purchase an additional CPU Core for your home computer? Each CPU Core " +
"lets you start with an additional Core Node in Hacking Missions.<br><br>" +
"Purchasing an additional core (for a total of " + (p.getHomeComputer().cpuCores + 1) + ") will " +
"cost " + numeralWrapper.formatMoney(cost));
"cost " + numeralWrapper.formatMoney(cost)
);
}
/**
* Create a popup that lets the player upgrade the RAM on his/her home computer
* @param p - Player object
* @param {IPlayer} p - Player object
*/
export function createUpgradeHomeRamPopup(p: IPlayer) {
const cost: number = p.getUpgradeHomeRamCost();
@ -255,15 +266,17 @@ export function createUpgradeHomeRamPopup(p: IPlayer) {
yesNoBoxClose();
});
yesNoBoxCreate("Would you like to purchase additional RAM for your home computer? <br><br>" +
yesNoBoxCreate(
"Would you like to purchase additional RAM for your home computer? <br><br>" +
"This will upgrade your RAM from " + ram + "GB to " + ram*2 + "GB. <br><br>" +
"This will cost " + numeralWrapper.format(cost, '$0.000a'));
"This will cost " + numeralWrapper.format(cost, '$0.000a')
);
}
/**
* Attempt to purchase a TOR router
* @param p - Player object
* @param {IPlayer} p - Player object
*/
export function purchaseTorRouter(p: IPlayer) {
if (p.hasTorRouter()) {
@ -285,7 +298,9 @@ export function purchaseTorRouter(p: IPlayer) {
p.getHomeComputer().serversOnNetwork.push(darkweb.ip);
darkweb.serversOnNetwork.push(p.getHomeComputer().ip);
dialogBoxCreate("You have purchased a Tor router!<br>" +
dialogBoxCreate(
"You have purchased a Tor router!<br>" +
"You now have access to the dark web from your home computer<br>" +
"Use the scan/scan-analyze commands to search for the dark web connection.");
"Use the scan/scan-analyze commands to search for the dark web connection."
);
}

@ -1,4 +1,10 @@
// Calculate a script's RAM usage
/**
* Implements RAM Calculation functionality.
*
* Uses the acorn.js library to parse a script's code into an AST and
* recursively walk through that AST, calculating RAM usage along
* the way
*/
import * as walk from "acorn-walk";
import { RamCalculationErrorCode } from "./RamCalculationErrorCodes";
@ -15,19 +21,26 @@ const specialReferenceWHILE = "__SPECIAL_referenceWhile";
// The global scope of a script is registered under this key during parsing.
const memCheckGlobalKey = ".__GLOBAL__";
// Calcluates the amount of RAM a script uses. Uses parsing and AST walking only,
// rather than NetscriptEvaluator. This is useful because NetscriptJS code does
// not work under NetscriptEvaluator.
/**
* Parses code into an AST and walks through it recursively to calculate
* RAM usage. Also accounts for imported modules.
* @param {Script[]} otherScripts - All other scripts on the server. Used to account for imported scripts
* @param {string} codeCopy - The code being parsed
* @param {WorkerScript} workerScript - Object containing RAM costs of Netscript functions. Also used to
* keep track of what functions have/havent been accounted for
*/
async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
try {
// Maps dependent identifiers to their dependencies.
//
// The initial identifier is __SPECIAL_INITIAL_MODULE__.__GLOBAL__.
// It depends on all the functions declared in the module, all the global scopes
// of its imports, and any identifiers referenced in this global scope. Each
// function depends on all the identifiers referenced internally.
// We walk the dependency graph to calculate RAM usage, given that some identifiers
// reference Netscript functions which have a RAM cost.
/**
* Maps dependent identifiers to their dependencies.
*
* The initial identifier is __SPECIAL_INITIAL_MODULE__.__GLOBAL__.
* It depends on all the functions declared in the module, all the global scopes
* of its imports, and any identifiers referenced in this global scope. Each
* function depends on all the identifiers referenced internally.
* We walk the dependency graph to calculate RAM usage, given that some identifiers
* reference Netscript functions which have a RAM cost.
*/
let dependencyMap = {};
// Scripts we've parsed.
@ -48,19 +61,20 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
}
}
// Splice all the references in.
//Spread syntax not supported in edge, use Object.assign instead
//dependencyMap = {...dependencyMap, ...result.dependencyMap};
// Splice all the references in
dependencyMap = Object.assign(dependencyMap, result.dependencyMap);
}
// Parse the initial module, which is the "main" script that is being run
const initialModule = "__SPECIAL_INITIAL_MODULE__";
parseCode(code, initialModule);
// Process additional modules, which occurs if the "main" script has any imports
while (parseQueue.length > 0) {
// Get the code from the server.
const nextModule = parseQueue.shift();
// Additional modules can either be imported from the web (in which case we use
// a dynamic import), or from other in-game scripts
let code;
if (nextModule.startsWith("https://") || nextModule.startsWith("http://")) {
try {
@ -136,10 +150,8 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
}
}
// Check if this identifier is a function in the workerscript env.
// Check if this identifier is a function in the workerScript environment.
// If it is, then we need to get its RAM cost.
//
// TODO it would be simpler to just reference a dictionary.
try {
function applyFuncRam(func) {
if (typeof func === "function") {
@ -170,7 +182,7 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
workerScript.loadedFns[ref] = true;
}
// This accounts for namespaces (Bladeburner, CodingCOntract)
// This accounts for namespaces (Bladeburner, CodingCpntract, etc.)
let func;
if (ref in workerScript.env.vars.bladeburner) {
func = workerScript.env.vars.bladeburner[ref];
@ -196,9 +208,12 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
}
}
// Parses one script and calculates its ram usage, for the global scope and each function.
// Returns a cost map and a dependencyMap for the module. Returns a reference map to be joined
// onto the main reference map, and a list of modules that need to be parsed.
/**
* Helper function that parses a single script. It returns a map of all dependencies,
* which are items in the code's AST that potentially need to be evaluated
* for RAM usage calculations. It also returns an array of additional modules
* that need to be parsed (i.e. are 'import'ed scripts).
*/
function parseOnlyCalculateDeps(code, currentModule) {
const ast = parse(code, {sourceType:"module", ecmaVersion: 8});
@ -296,6 +311,12 @@ function parseOnlyCalculateDeps(code, currentModule) {
return {dependencyMap: dependencyMap, additionalModules: additionalModules};
}
/**
* Calculate's a scripts RAM Usage
* @param {string} codeCopy - The script's code
* @param {Script[]} otherScripts - All other scripts on the server.
* Used to account for imported scripts
*/
export async function calculateRamUsage(codeCopy, otherScripts) {
// We don't need a real WorkerScript for this. Just an object that keeps
// track of whatever's needed for RAM calculations

@ -69,22 +69,20 @@ export class RunningScript {
if (script == null) { return; }
this.filename = script.filename;
this.args = args;
this.server = script.server; //IP Address only
this.server = script.server;
this.ramUsage = script.ramUsage;
}
log(txt: string): void {
if (this.logs.length > Settings.MaxLogCapacity) {
//Delete first element and add new log entry to the end.
//TODO Eventually it might be better to replace this with circular array
//to improve performance
this.logs.shift();
}
let logEntry = txt;
if (FconfSettings.ENABLE_TIMESTAMPS) {
logEntry = "[" + getTimestamp() + "] " + logEntry;
}
this.logs.push(logEntry);
this.logUpd = true;
}

@ -57,7 +57,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip
if (totalPrice == null) { return false; }
if (Player.money.lt(totalPrice)) {
if (tixApi) {
workerScript!.log(`ERROR: buyStock() failed because you do not have enough money to purchase this potiion. You need ${numeralWrapper.formatMoney(totalPrice)}`);
workerScript!.log(`ERROR: buyStock() failed because you do not have enough money to purchase this position. You need ${numeralWrapper.formatMoney(totalPrice)}`);
} else if (opts.suppressDialog !== true) {
dialogBoxCreate(`You do not have enough money to purchase this. You need ${numeralWrapper.formatMoney(totalPrice)}`);
}