diff --git a/src/Constants.js b/src/Constants.js
index 982abedda..27571077a 100644
--- a/src/Constants.js
+++ b/src/Constants.js
@@ -34,7 +34,7 @@ CONSTANTS = {
/* Script related things */
//Time (ms) it takes to run one operation in Netscript.
- CodeInstructionRunTime: 500,
+ CodeInstructionRunTime: 100,
//RAM Costs for different commands
ScriptWhileRamCost: 0.2,
@@ -258,6 +258,22 @@ CONSTANTS = {
"run [script] - Run a script
" +
"tail [script] - Displays a script's logs
" +
"top - Displays all active scripts and their RAM usage
" +
+ " Multithreading scripts
" +
+ "Scripts can be multithreaded. A multithreaded script runs the script's code once in each thread. The result is that " +
+ "every call to the hack(), grow(), and weaken() Netscript functions will have its effect multiplied by the number of scripts. " +
+ "For example, if a normal single-threaded script is able to hack $10,000, then running the same script with 5 threads would " +
+ "yield $50,000.
" +
+ "Each additional thread to a script will slightly increase the RAM usage for that thread. The total cost of running a script with " +
+ "n threads can be calculated with:
" +
+ "base cost * n * (1.02 ^ n)
" +
+ "where the base cost is the amount of RAM required to run the script with a single thread. In the terminal, you can run the " +
+ "'mem [scriptname] -t n' command to see how much RAM a script requires with n threads.
" +
+ "Every method for running a script has an option for making it multihreaded. To runa script with " +
+ "n threads from a Terminal:
" +
+ "run [scriptname] -t n
" +
+ "Using Netscript commands:
" +
+ "run('scriptname.script', m);
" +
+ "exec('scriptname.script, 'targetServer', n);
" +
" Notes about how scripts work offline
" +
" The scripts that you write and execute are interpreted in Javascript. For this " +
"reason, it is not possible for these scripts to run while offline (when the game is closed). " +
@@ -301,6 +317,9 @@ CONSTANTS = {
" >=
" +
" ==
" +
" !=
" +
+ " Arrays
" +
+ "Arrays are special container objects. Arrays can holy many values under a single name. Each value in the array " +
+ "can be accessed using an index number. To declare and access" +
" Functions
" +
"You can NOT define you own functions in Netscript (yet), but there are several built in functions that " +
"you may use:
" +
@@ -335,12 +354,17 @@ CONSTANTS = {
"relaysmtp(hostname/ip)
Run relaySMTP.exe on the target server. relaySMTP.exe must exist on your home computer. Does NOT work while offline
Example: relaysmtp('foodnstuff');
" +
"httpworm(hostname/ip)
Run HTTPWorm.exe on the target server. HTTPWorm.exe must exist on your home computer. Does NOT work while offline
Example: httpworm('foodnstuff');
" +
"sqlinject(hostname/ip)
Run SQLInject.exe on the target server. SQLInject.exe must exist on your home computer. Does NOT work while offline
Example: sqlinject('foodnstuff');
" +
- "run(script)
Run a script as a separate process. The argument that is passed in is the name of the script as a string. This function can only " +
- "be used to run scripts located on the same server. Returns true if the script is successfully started, and false otherwise. Requires a significant amount " +
+ "run(script, [numThreads])
Run a script as a separate process. The first argument that is passed in is the name of the script as a string. This function can only " +
+ "be used to run scripts located on the current server (the server running the script that calls this function). The second argument " +
+ "is optional, and it specifies how many threads to run the script with. If it is omitted, then the script is run single-threaded. " +
+ "This second argument must be a number that is greater than 0. " +
+ "Returns true if the script is successfully started, and false otherwise. Requires a significant amount " +
"of RAM to run this command. Does NOT work while offline
Example: run('hack-foodnstuff.script');
The example above will try and launch the 'hack-foodnstuff.script' script on " +
"the current server, if it exists.
" +
- "exec(script, hostname/ip)
Run a script as a separate process on another server. The first argument is the name of the script as a string. The " +
- "second argument is a string with the hostname or IP of the 'target server' on which to run the script. The specified script must exist on the target server. Returns " +
+ "exec(script, hostname/ip, [numThreads])
Run a script as a separate process on another server. The first argument is the name of the script as a string. The " +
+ "second argument is a string with the hostname or IP of the 'target server' on which to run the script. The specified script must exist on the target server. " +
+ "The third argument is optional, and it specifies how many threads to run the script with. If it is omitted, then the script is run single-threaded. " +
+ "This argument must be a number that is greater than 0. Returns " +
"true if the script is successfully started, and false otherwise. Does NOT work while offline
" +
"Example: exec('generic-hack.script', 'foodnstuff');
The example above will try to launch the script 'generic-hack.script' on the 'foodnstuff' server.
" +
"kill(script, [hostname/ip])
Kills a script on a server. The first argument must be a string with the name of the script. The name is case-sensitive. " +
@@ -400,7 +424,7 @@ CONSTANTS = {
"hacknetnodes[i].ram
Returns the amount of RAM on the corresponding Hacknet Node
" +
"hacknetnodes[i].cores
Returns the number of cores on the corresponding Hacknet Node
" +
"hacknetnodes[i].upgradeLevel(n)
Tries to upgrade the level of the corresponding Hacknet Node n times. The argument n must be a " +
- "positive integer. Returns true if the Hacknet Node's level is successfully upgraded n times, and false otherwise.
" +
+ "positive integer. Returns true if the Hacknet Node's level is successfully upgraded n times or up to the max level (200), and false otherwise.
" +
"hacknetnodes[i].upgradeRam()
Tries to upgrade the amount of RAM on the corresponding Hacknet Node. Returns true if the " +
"RAM is successfully upgraded, and false otherwise.
" +
"hacknetnodes[i].upgradeCore()
Attempts to purchase an additional core for the corresponding Hacknet Node. Returns true if the " +
@@ -535,6 +559,14 @@ CONSTANTS = {
"RAM Upgrades on your home computer",
Changelog:
+ "v0.20.2
" +
+ "-Fixed several small bugs
" +
+ "-Added basic array functionality to Netscript
" +
+ "-Added ability to run scripts with multiple threads. Running a script with n threads will multiply the effects of all " +
+ "hack(), grow(), and weaken() commands by n. However, running a script with multiple threads has drawbacks in terms of " +
+ "RAM usage. A script's ram usage when it is 'multithreaded' is calculated as: base cost * numThreads * (1.02 ^ numThreads). " +
+ "A script can be run multithreaded using the 'run [script] -t n' Terminal command or by passing in an argument to the " +
+ "run() and exec() Netscript commands. See documentation.
" +
"v0.20.1
" +
"-Fixed bug where sometimes scripts would crash without showing the error
" +
"-Added Deepscan programs to Dark Web
" +
@@ -653,7 +685,13 @@ CONSTANTS = {
LatestUpdate:
"v0.20.2
" +
- ""
+ "-Fixed several small bugs
" +
+ "-Added basic array functionality to Netscript
" +
+ "-Added ability to run scripts with multiple threads. Running a script with n threads will multiply the effects of all " +
+ "hack(), grow(), and weaken() commands by n. However, running a script with multiple threads has drawbacks in terms of " +
+ "RAM usage. A script's ram usage when it is 'multithreaded' is calculated as: base cost * numThreads * (1.02 ^ numThreads). " +
+ "A script can be run multithreaded using the 'run [script] -t n' Terminal command or by passing in an argument to the " +
+ "run() and exec() Netscript commands. See documentation.
" +
"v0.20.1
" +
"-Fixed bug where sometimes scripts would crash without showing the error
" +
"-Added Deepscan programs to Dark Web
" +
diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js
index c384f33f0..07162262a 100644
--- a/src/NetscriptEvaluator.js
+++ b/src/NetscriptEvaluator.js
@@ -40,18 +40,15 @@ function evaluate(exp, workerScript) {
}
try {
var res = env.get(exp.value);
- console.log(res);
if (exp.index) {
//If theres an index field, then this variable is supposed to be an array
//and the user needs to be indexing it
if (res.constructor === Array || res instanceof Array) {
- //Do array stuff here
var iPromise = evaluate(exp.index.value, workerScript);
iPromise.then(function(i) {
if (i >= res.length || i < 0) {
return reject(makeRuntimeRejectMsg(workerScript, "Out of bounds: Invalid index in [] operator"));
} else {
- //Evaluate here
return evaluate(res[i], workerScript);
}
}).then(function(res) {
diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js
index 4e186bd83..83d2c8384 100644
--- a/src/NetscriptFunctions.js
+++ b/src/NetscriptFunctions.js
@@ -9,17 +9,45 @@ function netscriptAssign(exp, workerScript) {
return reject(makeRuntimeRejectMsg(workerScript, "Cannot assign to " + JSON.stringify(exp.left)));
}
- var expRightPromise = evaluate(exp.right, workerScript);
- expRightPromise.then(function(expRight) {
+ //Assigning an element in an array
+ if (exp.left.index) {
try {
- env.set(exp.left.value, expRight);
- } catch (e) {
- return reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString()));
+ var res = env.get(exp.left.value);
+ if (res.constructor === Array || res instanceof Array) {
+ var iPromise = evaluate(exp.left.index.value, workerScript);
+ iPromise.then(function(i) {
+ if (i >= res.length || i < 0) {
+ return reject(makeRuntimeRejectMsg(workerScript, "Out of bounds: Invalid index in [] operator"));
+ } else {
+ res[i].type = exp.right.type;
+ res[i].value = exp.right.value;
+ return resolve(false);
+ }
+ }).then(function(res) {
+ return resolve(res);
+ }).catch(function(e) {
+ return reject(e);
+ });
+ } else {
+ console.log("here");
+ return reject(makeRuntimeRejectMsg(workerScript, "Trying to access a non-array variable using the [] operator"));
+ }
+ } catch(e) {
+ return reject(makeRuntimeRejectMsg(workerScript, e.toString()));
}
- resolve(false); //Return false so this doesnt cause conditionals to evaluate
- }, function(e) {
- reject(e);
- });
+ } else {
+ var expRightPromise = evaluate(exp.right, workerScript);
+ expRightPromise.then(function(expRight) {
+ try {
+ env.set(exp.left.value, expRight);
+ } catch (e) {
+ return reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString()));
+ }
+ resolve(false); //Return false so this doesnt cause conditionals to evaluate
+ }, function(e) {
+ reject(e);
+ });
+ }
});
}