Refactored Code using Bluebird Promises. Still has memory issues. Added Buy Max and Sell All to stock market UI

This commit is contained in:
danielyxie 2017-11-01 17:56:30 -05:00
parent 7c4ac00f5a
commit 52967d7f9d
7 changed files with 9443 additions and 3119 deletions

11001
dist/bundle.js vendored

File diff suppressed because one or more lines are too long

@ -1,3 +1,6 @@
import {Locations} from "./src/Location.js";
import {getRandomInt} from "../utils/HelperFunctions.js";
/* /*
Products Products
For certain industries, players can creat their own custom products For certain industries, players can creat their own custom products
@ -204,3 +207,201 @@ Industries:
will fluctuate based on company performance. Then you can sell whatever will fluctuate based on company performance. Then you can sell whatever
shares you have left on the stock market. shares you have left on the stock market.
*/ */
var TOTALSHARES = 1000000000; //Total number of shares you have at your company
var Materials = {
Water: 11,
Energy: 12,
Food: 13,
Plants: 14,
Metal: 15,
Hardware: 16,
Chemicals: 17,
RealEstate: 18,
Drugs: 19,
Robots: 20,
AICores:21,
SciResearch: 22
}
function Material(params={}) {
this.name = params.name ? params.name : "";
this.qty = 0;
this.qlt = 0;
this.dmd = 0;
this.cmp = 0;
this.mku = 0;
//How much space it takes in a Warehouse
this.siz = params.size ? params.size : 0;
this.purc = 0; //How much of this material is being purchased per second
this.cost = 0; //$ Cost per material
this.req = params.req ? params.req : [];
}
function Product(params={}) {
"use strict"
this.name = params.name ? params.name : 0;
this.dmd = params.demand ? params.demand : 0;
this.cmp = params.competition ? params.competition : 0;
this.mku = params.markup ? params.markup : 0;
this.qlt = params.quality ? params.quality : 0;
this.qty = 0;
this.per = params.performance ? params.performance : 0;
this.dur = params.durability ? params.durability : 0;
this.rel = params.reliability ? params.reliability : 0;
this.aes = params.aesthetics ? params.aesthetics : 0;
this.fea = params.features ? params.features : 0;
this.loc = params.location ? params.location : "";
this.siz = params.size ? params.size : 0; //How much space it takes in the warehouse
//Material requirements. An object that maps the name of a material to how much it requires
this.req = params.req ? params.req : {};
}
var Industries = {
Energy: 50,
Utilities: 51,
Agriculture: 52,
Fishing: 53,
Mining: 54,
Food: 55,
Tobacco: 56,
Chemical: 57,
Pharmaceutical: 58,
Computer: 59,
Robotics: 60,
Software: 61,
Healthcare: 62,
RealEstate: 63,
}
function Industry(params={}) {
"use strict"
this.offices = { //Maps locations to offices. 0 if no office at that location
Locations.Aevum: 0,
Locations.Chonqing: 0,
Locations.Sector12: 0,
Locations.NewTokyo: 0,
Locations.Ishima: 0,
Locations.Volhaven: 0
};
this.warehouses = { //Maps locations to warehouses. 0 if no warehouse at that location
Locations.Aevum: 0,
Locations.Chonqing: 0,
Locations.Sector12: 0,
Locations.NewTokyo: 0,
Locations.Ishima: 0,
Locations.Volhaven: 0
};
this.type = params.type ? params.type : 0;
this.materials = {};
this.products = {};
this.awareness = 0;
this.popularity = 0;
this.startingCost = 0;
/* The following are factors for how much production/other things are increased by
different factors. The production increase always has diminishing returns,
and they are all reprsented by inverse exponentials.
The number for these properties represent the denominator in the inverse
exponential (aka higher number = more diminishing returns); */
this.reFac = 0; //Real estate Factor
this.sciFac = 0; //Scientific Research Factor
this.hwFac = 0; //Hardware factor
this.robFac = 0; //Robotics Factor
this.aiFac = 0; //AI Cores factor;
this.advFac = 0; //Advertising factor
this.init();
}
Industry.prototype.init = function() {
//Set the unique properties of an industry (how much its affected by real estate/scientific research, etc.)
switch (this.type) {
case Industries.Energy:
break;
case Industries.Utilities:
break;
case Industries.Agriculture:
break;
}
}
var EmployeePositions = {
Operations: 1,
Engineer: 2,
Business: 3,
Accounting: 4,
Management: 5,
RandD: 6
}
function Employee(params={}) {
"use strict"
if (!(this instanceof Employee)) {
return new Employee(params);
}
this.name = params.name ? params.name : "Bobby";
this.mor = params.morale ? params.morale : getRandomInt(50, 100);
this.hap = params.happiness ? params.happiness : getRandomInt(50, 100);
this.ene = params.energy ? params.energy : getRandomInt(50, 100);
this.age = params.age ? params.age : getRandomInt(20, 50);
this.int = params.intelligence ? params.intelligence : getRandomInt(10, 50);
this.cha = params.charisma ? params.charisma : getRandomInt(10, 50);
this.exp = params.experience ? params.experience : getRandomInt(10, 50);
this.cre = params.creativity ? params.creativity : getRandomInt(10, 50);
this.eff = params.efficiency ? params.efficiency : getRandomInt(10, 50);
this.sal = params.salary ? params.salary : getRandomInt(0.1, 5);
this.pro = 0; //Calculated
this.off = params.officeSpace ? params.officeSpace : {};
this.loc = params.officeSpace ? params.officeSpace.loc : "";
this.pos = 0;
}
var OfficeSpaceTiers = {
Basic: 7,
Enhanced: 8,
Luxurious: 9,
Extravagant: 10
}
function OfficeSpace(params={}) {
"use strict"
this.loc = params.loc ? params.loc : "";
this.cost = params.cost ? params.cost : 1;
this.size = params.size ? params.size : 1;
this.comf = params.comfort ? params.comfort : 1;
this.beau = parms.beauty ? params.beauty : 1;
this.tier = OfficeSpaceTiers.Basic;
this.employees = [];
}
function Warehouse(params={}) {
"use strict"
this.loc = params.loc ? params.loc : "";
this.size = params.size ? params.size : 0;
this.materials = {};
this.products = {};
}
function Company() {
"use strict"
this.industries = [];
//Financial stats
this.funds = 0;
this.revenue = 0;
this.expenses = 0;
this.valuation = 0; //Private investory valuation of company before you go public.
this.numShares = TOTALSHARES;
this.sharePrice = 0;
}

@ -13,72 +13,79 @@ import {printArray} from "../utils/HelperFunctions.js";
import {isValidIPAddress} from "../utils/IPAddress.js"; import {isValidIPAddress} from "../utils/IPAddress.js";
import {isString} from "../utils/StringHelperFunctions.js"; import {isString} from "../utils/StringHelperFunctions.js";
var Promise = require("bluebird");
Promise.config({
warnings: false,
longStackTraces: false,
cancellation: true,
monitoring: false
});
/* Evaluator /* Evaluator
* Evaluates/Interprets the Abstract Syntax Tree generated by Acorns parser * Evaluates/Interprets the Abstract Syntax Tree generated by Acorns parser
* *
* Returns a promise * Returns a promise
*/ */
function evaluate(exp, workerScript) { function evaluate(exp, workerScript) {
return new Promise(function(resolve, reject) { /* return new Promise(function(resolve, reject) {*/
return Promise.delay(Settings.CodeInstructionRunTime).then(function() {
var env = workerScript.env; var env = workerScript.env;
if (env.stopFlag) {return reject(workerScript);} if (env.stopFlag) {return Promise.reject(workerScript);}
if (exp == null) { if (exp == null) {
return reject(makeRuntimeRejectMsg(workerScript, "Error: NULL expression")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Error: NULL expression"));
} }
setTimeout(function() { if (env.stopFlag) {return Promise.reject(workerScript);}
if (env.stopFlag) {return reject(workerScript);}
switch (exp.type) { switch (exp.type) {
case "BlockStatement": case "BlockStatement":
case "Program": case "Program":
var evaluateProgPromise = evaluateProg(exp, workerScript, 0); //TODO: make every block/program use individual enviroment var evaluateProgPromise = evaluateProg(exp, workerScript, 0); //TODO: make every block/program use individual enviroment
evaluateProgPromise.then(function(w) { return evaluateProgPromise.then(function(w) {
resolve(workerScript); return Promise.resolve(workerScript);
}, function(e) { }).catch(function(e) {
if (e.constructor === Array && e.length === 2 && e[0] === "RETURNSTATEMENT") { if (e.constructor === Array && e.length === 2 && e[0] === "RETURNSTATEMENT") {
reject(e); return Promise.reject(e);
} else if (isString(e)) { } else if (isString(e)) {
workerScript.errorMessage = e; workerScript.errorMessage = e;
reject(workerScript); return Promise.reject(workerScript);
} else if (e instanceof WorkerScript) { } else if (e instanceof WorkerScript) {
reject(e); return Promise.reject(e);
} else { } else {
reject(workerScript); return Promise.reject(workerScript);
} }
}); });
break; break;
case "Literal": case "Literal":
resolve(exp.value); return Promise.resolve(exp.value);
break; break;
case "Identifier": case "Identifier":
if (!(exp.name in env.vars)){ if (!(exp.name in env.vars)){
reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.name + " not defined")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.name + " not defined"));
} }
resolve(env.get(exp.name)) return Promise.resolve(env.get(exp.name))
break; break;
case "ExpressionStatement": case "ExpressionStatement":
var e = evaluate(exp.expression, workerScript); return evaluate(exp.expression, workerScript);
e.then(function(res) {
resolve(res);
}, function(e) {
reject(e);
});
break; break;
case "ArrayExpression": case "ArrayExpression":
var argPromises = exp.elements.map(function(arg) { var argPromises = exp.elements.map(function(arg) {
return evaluate(arg, workerScript); return evaluate(arg, workerScript);
}); });
Promise.all(argPromises).then(function(array) { return Promise.all(argPromises).then(function(array) {
resolve(array) return Promise.resolve(array)
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
break; break;
case "CallExpression": case "CallExpression":
evaluate(exp.callee, workerScript).then(function(func) { return evaluate(exp.callee, workerScript).then(function(func) {
/*
var argPromises = exp.arguments.map(function(arg) { var argPromises = exp.arguments.map(function(arg) {
return evaluate(arg, workerScript); return evaluate(arg, workerScript);
}); });
Promise.all(argPromises).then(function(args) { Promise.all(argPromises).then(function(args) {*/
return Promise.map(exp.arguments, function(arg) {
return evaluate(arg, workerScript);
}).then(function(args) {
if (func instanceof Node) { //Player-defined function if (func instanceof Node) { //Player-defined function
//Create new Environment for the function //Create new Environment for the function
//Should be automatically garbage collected... //Should be automatically garbage collected...
@ -101,129 +108,122 @@ function evaluate(exp, workerScript) {
funcWorkerScript.env = funcEnv; funcWorkerScript.env = funcEnv;
workerScript.fnWorker = funcWorkerScript; workerScript.fnWorker = funcWorkerScript;
evaluate(func.body, funcWorkerScript).then(function(res) { return evaluate(func.body, funcWorkerScript).then(function(res) {
//If the function finished successfuly, that means there //If the function finished successfuly, that means there
//was no return statement since a return statement rejects. So resolve to null //was no return statement since a return statement rejects. So resolve to null
resolve(null);
workerScript.fnWorker = null; workerScript.fnWorker = null;
return Promise.resolve(null);
}).catch(function(e) { }).catch(function(e) {
if (e.constructor === Array && e.length === 2 && e[0] === "RETURNSTATEMENT") { if (e.constructor === Array && e.length === 2 && e[0] === "RETURNSTATEMENT") {
//Return statement from function //Return statement from function
resolve(e[1]); return Promise.resolve(e[1]);
workerScript.fnWorker = null; workerScript.fnWorker = null;
} else if (isString(e)) { } else if (isString(e)) {
reject(makeRuntimeRejectMsg(workerScript, e)); return Promise.reject(makeRuntimeRejectMsg(workerScript, e));
} else if (e instanceof WorkerScript) { } else if (e instanceof WorkerScript) {
//Parse out the err message from the WorkerScript and re-reject //Parse out the err message from the WorkerScript and re-reject
var errorMsg = e.errorMessage; var errorMsg = e.errorMessage;
var errorTextArray = errorMsg.split("|"); var errorTextArray = errorMsg.split("|");
if (errorTextArray.length === 4) { if (errorTextArray.length === 4) {
errorMsg = errorTextArray[3]; errorMsg = errorTextArray[3];
reject(makeRuntimeRejectMsg(workerScript, errorMsg)); return Promise.reject(makeRuntimeRejectMsg(workerScript, errorMsg));
} else { } else {
if (env.stopFlag) { if (env.stopFlag) {
reject(workerScript); return Promise.reject(workerScript);
} else { } else {
reject(makeRuntimeRejectMsg(workerScript, "Error in one of your functions. Could not identify which function")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Error in one of your functions. Could not identify which function"));
} }
} }
} else if (e instanceof Error) { } else if (e instanceof Error) {
reject(makeRuntimeRejectMsg(workerScript, e.toString())); return Promise.reject(makeRuntimeRejectMsg(workerScript, e.toString()));
} }
}); });
} else if (exp.callee.type == "MemberExpression"){ } else if (exp.callee.type == "MemberExpression"){
evaluate(exp.callee.object, workerScript).then(function(object) { return evaluate(exp.callee.object, workerScript).then(function(object) {
try { try {
var res = func.apply(object,args); var res = func.apply(object,args);
resolve(res); return Promise.resolve(res);
} catch (e) { } catch (e) {
reject(makeRuntimeRejectMsg(workerScript, e)); return Promise.reject(makeRuntimeRejectMsg(workerScript, e));
} }
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
} else { } else {
try { try {
var out = func.apply(null,args); var out = func.apply(null,args);
if (out instanceof Promise){ if (out instanceof Promise){
out.then(function(res) { return out.then(function(res) {
resolve(res) return Promise.resolve(res)
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
} else { } else {
resolve(out); return Promise.resolve(out);
} }
} catch (e) { } catch (e) {
if (isScriptErrorMessage(e)) { if (isScriptErrorMessage(e)) {
reject(e); return Promise.reject(e);
} else { } else {
reject(makeRuntimeRejectMsg(workerScript, e)); return Promise.reject(makeRuntimeRejectMsg(workerScript, e));
} }
} }
} }
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
break; break;
case "MemberExpression": case "MemberExpression":
var pObject = evaluate(exp.object, workerScript); return evaluate(exp.object, workerScript).then(function(object) {
pObject.then(function(object) {
if (exp.computed){ if (exp.computed){
var p = evaluate(exp.property, workerScript); return evaluate(exp.property, workerScript).then(function(index) {
p.then(function(index) {
if (index >= object.length) { if (index >= object.length) {
return reject(makeRuntimeRejectMsg(workerScript, "Invalid index for arrays")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid index for arrays"));
} }
resolve(object[index]); return Promise.resolve(object[index]);
}).catch(function(e) { }).catch(function(e) {
reject(makeRuntimeRejectMsg(workerScript, "Invalid MemberExpression")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid MemberExpression"));
}); });
} else { } else {
try { try {
resolve(object[exp.property.name]) return Promise.resolve(object[exp.property.name])
} catch (e) { } catch (e) {
return reject(makeRuntimeRejectMsg(workerScript, "Failed to get property: " + e.toString())); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to get property: " + e.toString()));
} }
} }
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
break; break;
case "LogicalExpression": case "LogicalExpression":
case "BinaryExpression": case "BinaryExpression":
var p = evalBinary(exp, workerScript, resolve, reject); return evalBinary(exp, workerScript).then(function(res) {
p.then(function(res) { return Promise.resolve(res);
resolve(res);
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
break; break;
case "UnaryExpression": case "UnaryExpression":
var p = evalUnary(exp, workerScript, resolve, reject); return evalUnary(exp, workerScript).then(function(res) {
p.then(function(res) { return Promise.resolve(res);
resolve(res);
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
break; break;
case "AssignmentExpression": case "AssignmentExpression":
var p = evalAssignment(exp, workerScript); return evalAssignment(exp, workerScript).then(function(res) {
p.then(function(res) { return Promise.resolve(res);
resolve(res);
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
break; break;
case "UpdateExpression": case "UpdateExpression":
if (exp.argument.type==="Identifier"){ if (exp.argument.type==="Identifier"){
if (exp.argument.name in env.vars){ if (exp.argument.name in env.vars){
if (exp.prefix){ if (exp.operator === "++" || exp.operator === "--") {
resolve(env.get(exp.argument.name))
}
switch (exp.operator) { switch (exp.operator) {
case "++": case "++":
env.set(exp.argument.name,env.get(exp.argument.name)+1); env.set(exp.argument.name,env.get(exp.argument.name)+1);
@ -231,191 +231,188 @@ function evaluate(exp, workerScript) {
case "--": case "--":
env.set(exp.argument.name,env.get(exp.argument.name)-1); env.set(exp.argument.name,env.get(exp.argument.name)-1);
break; break;
default: break;
}
return Promise.resolve(env.get(exp.argument.name));
}
//Not sure what prefix UpdateExpressions there would be besides ++/--
if (exp.prefix){
return Promise.resolve(env.get(exp.argument.name))
}
switch (exp.operator){
default: default:
reject(makeRuntimeRejectMsg(workerScript, "Unrecognized token: " + exp.type + ". You are trying to use code that is currently unsupported")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unrecognized token: " + exp.type + ". You are trying to use code that is currently unsupported"));
} }
if (env.prefix){ return Promise.resolve(env.get(exp.argument.name))
return;
}
resolve(env.get(exp.argument.name))
} else { } else {
reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.argument.name + " not defined")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.argument.name + " not defined"));
} }
} else { } else {
reject(makeRuntimeRejectMsg(workerScript, "argument must be an identifier")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "argument must be an identifier"));
} }
break; break;
case "EmptyStatement": case "EmptyStatement":
resolve(false); return Promise.resolve(false);
break; break;
case "ReturnStatement": case "ReturnStatement":
console.log("Evaluating Return Statement"); return evaluate(exp.argument, workerScript).then(function(res) {
//var lineNum = getErrorLineNumber(exp, workerScript); return Promise.reject(["RETURNSTATEMENT", res]);
//reject(makeRuntimeRejectMsg(workerScript, "Return statements are not yet implemented in Netscript (line " + (lineNum+1) + ")"));
evaluate(exp.argument, workerScript).then(function(res) {
reject(["RETURNSTATEMENT", res]);
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
break; break;
case "BreakStatement": case "BreakStatement":
reject("BREAKSTATEMENT"); return Promise.reject("BREAKSTATEMENT");
break; break;
case "ContinueStatement": case "ContinueStatement":
reject("CONTINUESTATEMENT"); return Promise.reject("CONTINUESTATEMENT");
break; break;
case "IfStatement": case "IfStatement":
evaluateIf(exp, workerScript).then(function(forLoopRes) { return evaluateIf(exp, workerScript).then(function(forLoopRes) {
resolve(forLoopRes); return Promise.resolve(forLoopRes);
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
break; break;
case "SwitchStatement": case "SwitchStatement":
var lineNum = getErrorLineNumber(exp, workerScript); var lineNum = getErrorLineNumber(exp, workerScript);
reject(makeRuntimeRejectMsg(workerScript, "Switch statements are not yet implemented in Netscript (line " + (lineNum+1) + ")")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Switch statements are not yet implemented in Netscript (line " + (lineNum+1) + ")"));
break;e break;
case "WhileStatement": case "WhileStatement":
evaluateWhile(exp, workerScript).then(function(forLoopRes) { return evaluateWhile(exp, workerScript).then(function(forLoopRes) {
resolve(forLoopRes); return Promise.resolve(forLoopRes);
}).catch(function(e) { }).catch(function(e) {
if (e == "BREAKSTATEMENT" || if (e == "BREAKSTATEMENT" ||
(e instanceof WorkerScript && e.errorMessage == "BREAKSTATEMENT")) { (e instanceof WorkerScript && e.errorMessage == "BREAKSTATEMENT")) {
return resolve("whileLoopBroken"); return Promise.resolve("whileLoopBroken");
} else { } else {
reject(e); return Promise.reject(e);
} }
}); });
break; break;
case "ForStatement": case "ForStatement":
evaluate(exp.init, workerScript).then(function(expInit) { return evaluate(exp.init, workerScript).then(function(expInit) {
return evaluateFor(exp, workerScript); return evaluateFor(exp, workerScript);
}).then(function(forLoopRes) { }).then(function(forLoopRes) {
resolve("forLoopDone"); return Promise.resolve("forLoopDone");
}).catch(function(e) { }).catch(function(e) {
if (e == "BREAKSTATEMENT" || if (e == "BREAKSTATEMENT" ||
(e instanceof WorkerScript && e.errorMessage == "BREAKSTATEMENT")) { (e instanceof WorkerScript && e.errorMessage == "BREAKSTATEMENT")) {
return resolve("forLoopBroken"); return Promise.resolve("forLoopBroken");
} else { } else {
reject(e); return Promise.reject(e);
} }
}); });
break; break;
case "FunctionDeclaration": case "FunctionDeclaration":
if (exp.id && exp.id.name) { if (exp.id && exp.id.name) {
env.set(exp.id.name, exp); env.set(exp.id.name, exp);
resolve(true); return Promise.resolve(true);
} else { } else {
var lineNum = getErrorLineNumber(exp, workerScript); var lineNum = getErrorLineNumber(exp, workerScript);
reject(makeRuntimeRejectMsg(workerScript, "Invalid function declaration at line " + lineNum+1)); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid function declaration at line " + lineNum+1));
} }
break; break;
default: default:
var lineNum = getErrorLineNumber(exp, workerScript); var lineNum = getErrorLineNumber(exp, workerScript);
reject(makeRuntimeRejectMsg(workerScript, "Unrecognized token: " + exp.type + " (line " + (lineNum+1) + "). This is currently unsupported in Netscript")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unrecognized token: " + exp.type + " (line " + (lineNum+1) + "). This is currently unsupported in Netscript"));
break; break;
} //End switch } //End switch
}, Settings.CodeInstructionRunTime); //End setTimeout, the Netscript operation run time }).catch(function(e) {
return Promise.reject(e);
}); // End Promise }); // End Promise
} }
function evalBinary(exp, workerScript){ function evalBinary(exp, workerScript){
return new Promise(function(resolve, reject) { return evaluate(exp.left, workerScript).then(function(expLeft) {
var expLeftPromise = evaluate(exp.left, workerScript); //Short circuiting
expLeftPromise.then(function(expLeft) {
if (expLeft == true && exp.operator === "||") { if (expLeft == true && exp.operator === "||") {
return resolve(true); return Promise.resolve(true);
} }
if (expLeft == false && exp.operator === "&&") { if (expLeft == false && exp.operator === "&&") {
return resolve(false); return Promise.resolve(false);
} }
var expRightPromise = evaluate(exp.right, workerScript); return evaluate(exp.right, workerScript).then(function(expRight) {
expRightPromise.then(function(expRight) {
switch (exp.operator){ switch (exp.operator){
case "===": case "===":
case "==": case "==":
resolve(expLeft===expRight); return Promise.resolve(expLeft===expRight);
break; break;
case "!==": case "!==":
case "!=": case "!=":
resolve(expLeft!==expRight); return Promise.resolve(expLeft!==expRight);
break; break;
case "<": case "<":
resolve(expLeft<expRight); return Promise.resolve(expLeft<expRight);
break; break;
case "<=": case "<=":
resolve(expLeft<=expRight); return Promise.resolve(expLeft<=expRight);
break; break;
case ">": case ">":
resolve(expLeft>expRight); return Promise.resolve(expLeft>expRight);
break; break;
case ">=": case ">=":
resolve(expLeft>=expRight); return Promise.resolve(expLeft>=expRight);
break; break;
case "+": case "+":
resolve(expLeft+expRight); return Promise.resolve(expLeft+expRight);
break; break;
case "-": case "-":
resolve(expLeft-expRight); return Promise.resolve(expLeft-expRight);
break; break;
case "*": case "*":
resolve(expLeft*expRight); return Promise.resolve(expLeft*expRight);
break; break;
case "/": case "/":
if (expRight === 0) { if (expRight === 0) {
reject(makeRuntimeRejectMsg(workerScript, "ERROR: Divide by zero")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "ERROR: Divide by zero"));
} else { } else {
resolve(expLeft/expRight); return Promise.resolve(expLeft/expRight);
} }
break; break;
case "%": case "%":
resolve(expLeft%expRight); return Promise.resolve(expLeft%expRight);
break; break;
case "in": case "in":
resolve(expLeft in expRight); return Promise.resolve(expLeft in expRight);
break; break;
case "instanceof": case "instanceof":
resolve(expLeft instanceof expRight); return Promise.resolve(expLeft instanceof expRight);
break; break;
case "||": case "||":
resolve(expLeft || expRight); return Promise.resolve(expLeft || expRight);
break; break;
case "&&": case "&&":
resolve(expLeft && expRight); return Promise.resolve(expLeft && expRight);
break; break;
default: default:
reject(makeRuntimeRejectMsg(workerScript, "Unsupported operator: " + exp.operator)); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unsupported operator: " + exp.operator));
} }
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
}); });
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
});
}); });
} }
function evalUnary(exp, workerScript){ function evalUnary(exp, workerScript){
var env = workerScript.env; var env = workerScript.env;
return new Promise(function(resolve, reject) { if (env.stopFlag) {return Promise.reject(workerScript);}
if (env.stopFlag) {return reject(workerScript);} return evaluate(exp.argument, workerScript).then(function(res) {
var p = evaluate(exp.argument, workerScript);
p.then(function(res) {
if (exp.operator == "!") { if (exp.operator == "!") {
resolve(!res); return Promise.resolve(!res);
} else if (exp.operator == "-") { } else if (exp.operator == "-") {
if (isNaN(res)) { if (isNaN(res)) {
resolve(res); return Promise.resolve(res);
} else { } else {
resolve(-1 * res); return Promise.resolve(-1 * res);
} }
} else { } else {
reject(makeRuntimeRejectMsg(workerScript, "Unimplemented unary operator: " + exp.operator)); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unimplemented unary operator: " + exp.operator));
} }
}).catch(function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
});
}); });
} }
@ -423,59 +420,52 @@ function evalUnary(exp, workerScript){
//The return value is an array of the form: //The return value is an array of the form:
// [0th index (leftmost), array name, 1st index, 2nd index, ...] // [0th index (leftmost), array name, 1st index, 2nd index, ...]
function getArrayElement(exp, workerScript) { function getArrayElement(exp, workerScript) {
return new Promise(function(resolve, reject) {
var indices = []; var indices = [];
var iPromise = evaluate(exp.property, workerScript); return evaluate(exp.property, workerScript).then(function(idx) {
iPromise.then(function(idx) {
if (isNaN(idx)) { if (isNaN(idx)) {
return reject(makeRuntimeRejectMsg(workerScript, "Invalid access to array. Index is not a number: " + idx)); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Invalid access to array. Index is not a number: " + idx));
} else { } else {
if (exp.object.name === undefined && exp.object.object) { if (exp.object.name === undefined && exp.object.object) {
var recursePromise = getArrayElement(exp.object, workerScript); return getArrayElement(exp.object, workerScript).then(function(res) {
recursePromise.then(function(res) {
res.push(idx); res.push(idx);
indices = res; indices = res;
return resolve(indices); return Promise.resolve(indices);
}).catch(function(e) { }).catch(function(e) {
return reject(e); return Promise.reject(e);
}); });
} else { } else {
indices.push(idx); indices.push(idx);
indices.push(exp.object.name); indices.push(exp.object.name);
return resolve(indices); return Promise.resolve(indices);
} }
} }
}).catch(function(e) { }).catch(function(e) {
console.log(e); console.log(e);
console.log("Error getting index in getArrayElement: " + e.toString()); console.log("Error getting index in getArrayElement: " + e.toString());
return reject(e); return Promise.reject(e);
});
}); });
} }
function evalAssignment(exp, workerScript) { function evalAssignment(exp, workerScript) {
var env = workerScript.env; var env = workerScript.env;
return new Promise(function(resolve, reject) { if (env.stopFlag) {return Promise.reject(workerScript);}
if (env.stopFlag) {return reject(workerScript);}
if (exp.left.type != "Identifier" && exp.left.type != "MemberExpression") { if (exp.left.type != "Identifier" && exp.left.type != "MemberExpression") {
return reject(makeRuntimeRejectMsg(workerScript, "Cannot assign to " + JSON.stringify(exp.left))); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Cannot assign to " + JSON.stringify(exp.left)));
} }
if (exp.operator !== "=" && !(exp.left.name in env.vars)){ if (exp.operator !== "=" && !(exp.left.name in env.vars)){
return reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.left.name + " not defined")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "variable " + exp.left.name + " not defined"));
} }
var expRightPromise = evaluate(exp.right, workerScript); return evaluate(exp.right, workerScript).then(function(expRight) {
expRightPromise.then(function(expRight) {
if (exp.left.type == "MemberExpression") { if (exp.left.type == "MemberExpression") {
//Assign to array element //Assign to array element
//Array object designed by exp.left.object.name //Array object designed by exp.left.object.name
//Index designated by exp.left.property //Index designated by exp.left.property
var getArrayElementPromise = getArrayElement(exp.left, workerScript); return getArrayElement(exp.left, workerScript).then(function(res) {
getArrayElementPromise.then(function(res) {
if (!(res instanceof Array) || res.length < 2) { if (!(res instanceof Array) || res.length < 2) {
return reject(makeRuntimeRejectMsg(workerScript, "Error evaluating array assignment. This is (probably) a bug please report to game dev")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Error evaluating array assignment. This is (probably) a bug please report to game dev"));
} }
//The array name is the second value //The array name is the second value
@ -483,32 +473,10 @@ function evalAssignment(exp, workerScript) {
arrName = arrName[0]; arrName = arrName[0];
env.setArrayElement(arrName, res, expRight); env.setArrayElement(arrName, res, expRight);
return resolve(false); return Promise.resolve(false);
}).catch(function(e) { }).catch(function(e) {
return reject(e); return Promise.reject(e);
}); });
/*
var name = exp.left.object.name;
if (!(name in env.vars)){
reject(makeRuntimeRejectMsg(workerScript, "variable " + name + " not defined"));
}
var arr = env.get(name);
if (arr.constructor === Array || arr instanceof Array) {
var iPromise = evaluate(exp.left.property, workerScript);
iPromise.then(function(idx) {
if (isNaN(idx)) {
return reject(makeRuntimeRejectMsg(workerScript, "Invalid access to array. Index is not a number: " + idx));
} else if (idx >= arr.length || idx < 0) {
return reject(makeRuntimeRejectMsg(workerScript, "Out of bounds: Invalid index in [] operator"));
} else {
env.setArrayElement(name, idx, expRight);
}
}).catch(function(e) {
return reject(e);
});
} else {
return reject(makeRuntimeRejectMsg(workerScript, "Trying to access a non-array variable using the [] operator"));
}*/
} else { } else {
//Other assignments //Other assignments
try { try {
@ -532,203 +500,147 @@ function evalAssignment(exp, workerScript) {
env.set(exp.left.name,env.get(exp.left.name) % expRight); env.set(exp.left.name,env.get(exp.left.name) % expRight);
break; break;
default: default:
reject(makeRuntimeRejectMsg(workerScript, "Bitwise assignment is not implemented")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Bitwise assignment is not implemented"));
} }
resolve(false); return Promise.resolve(false);
} catch (e) { } catch (e) {
return reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString())); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString()));
} }
} }
//resolve(false); //Return false so this doesnt cause conditionals to evaluate
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
});
}); });
} }
function evaluateIf(exp, workerScript, i) { function evaluateIf(exp, workerScript, i) {
var env = workerScript.env; var env = workerScript.env;
return new Promise(function(resolve, reject) { return evaluate(exp.test, workerScript).then(function(condRes) {
evaluate(exp.test, workerScript).then(function(condRes) {
if (condRes) { if (condRes) {
evaluate(exp.consequent, workerScript).then(function(res) { return evaluate(exp.consequent, workerScript).then(function(res) {
resolve(true); return Promise.resolve(true);
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
}); });
} else if (exp.alternate) { } else if (exp.alternate) {
evaluate(exp.alternate, workerScript).then(function(res) { return evaluate(exp.alternate, workerScript).then(function(res) {
resolve(true); return Promise.resolve(true);
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
}); });
} else { } else {
resolve("endIf") return Promise.resolve("endIf");
} }
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
});
}); });
} }
//Evaluate the looping part of a for loop (Initialization block is NOT done in here) //Evaluate the looping part of a for loop (Initialization block is NOT done in here)
function evaluateFor(exp, workerScript) { function evaluateFor(exp, workerScript) {
var env = workerScript.env; var env = workerScript.env;
return new Promise(function(resolve, reject) { if (env.stopFlag) {return Promise.reject(workerScript);}
if (env.stopFlag) {reject(workerScript); return;} return evaluate(exp.test, workerScript).then(function(resCond) {
var pCond = evaluate(exp.test, workerScript);
pCond.then(function(resCond) {
if (resCond) { if (resCond) {
//Run the for loop code //Execute code (body), update, and then recurse
var pBody = evaluate(exp.body, workerScript); return evaluate(exp.body, workerScript).then(function(resCode) {
//After the code executes make a recursive call return evaluate(exp.update, workerScript);
pBody.then(function(resCode) { }).catch(function(e) {
var pUpdate = evaluate(exp.update, workerScript);
pUpdate.then(function(resPostloop) {
var recursiveCall = evaluateFor(exp, workerScript);
recursiveCall.then(function(foo) {
resolve("endForLoop");
}, function(e) {
reject(e);
});
}, function(e) {
reject(e);
});
}, function(e) {
if (e == "CONTINUESTATEMENT" || if (e == "CONTINUESTATEMENT" ||
(e instanceof WorkerScript && e.errorMessage == "CONTINUESTATEMENT")) { (e instanceof WorkerScript && e.errorMessage == "CONTINUESTATEMENT")) {
//Continue statement, recurse to next iteration //Continue statement, recurse to next iteration
var pUpdate = evaluate(exp.update, workerScript); return evaluate(exp.update, workerScript).then(function(resPostloop) {
pUpdate.then(function(resPostloop) { return evaluateFor(exp, workerScript);
var recursiveCall = evaluateFor(exp, workerScript); }).then(function(foo) {
recursiveCall.then(function(foo) { return Promise.resolve("endForLoop");
resolve("endForLoop"); }).catch(function(e) {
}, function(e) { return Promise.reject(e);
reject(e);
});
}, function(e) {
reject(e);
}); });
} else { } else {
reject(e); return Promise.reject(e);
} }
}).then(function(resPostloop) {
return evaluateFor(exp, workerScript);
}).then(function(foo) {
return Promise.resolve("endForLoop");
}).catch(function(e) {
return Promise.reject(e);
}); });
} else { } else {
resolve("endForLoop"); //Doesn't need to resolve to any particular value return Promise.resolve("endForLoop"); //Doesn't need to resolve to any particular value
} }
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
});
}); });
} }
function evaluateWhile(exp, workerScript) { function evaluateWhile(exp, workerScript) {
var env = workerScript.env; var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
return new Promise(function(resolve, reject) { return Promise.delay(CONSTANTS.CodeInstructionRunTime).then(function() {
if (env.stopFlag) {reject(workerScript); return;} return evaluate(exp.test, workerScript);
}).then(function(resCond) {
var pCond = new Promise(function(resolve, reject) {
setTimeout(function() {
var evaluatePromise = evaluate(exp.test, workerScript);
evaluatePromise.then(function(resCond) {
resolve(resCond);
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
});
pCond.then(function(resCond) {
if (resCond) { if (resCond) {
//Run the while loop code return evaluate(exp.body, workerScript).then(function(resCode) {
var pCode = new Promise(function(resolve, reject) { return Promise.resolve(resCode);
setTimeout(function() { }).catch(function(e) {
var evaluatePromise = evaluate(exp.body, workerScript);
evaluatePromise.then(function(resCode) {
resolve(resCode);
}, function(e) {
if (e == "CONTINUESTATEMENT" || if (e == "CONTINUESTATEMENT" ||
(e instanceof WorkerScript && e.errorMessage == "CONTINUESTATEMENT")) { (e instanceof WorkerScript && e.errorMessage == "CONTINUESTATEMENT")) {
//Continue statement, recurse //Continue statement, recurse
var recursiveCall = evaluateWhile(exp, workerScript); return evaluateWhile(exp, workerScript).then(function(foo) {
recursiveCall.then(function(foo) { return Promise.resolve("endWhileLoop");
resolve("endWhileLoop");
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
}); });
} else { } else {
reject(e); return Promise.reject(e);
} }
}); }).then(function(resCode) {
}, CONSTANTS.CodeInstructionRunTime); return evaluateWhile(exp, workerScript).then(function(foo) {
}); return Promise.resolve("endWhileLoop");
//After the code executes make a recursive call
pCode.then(function(resCode) {
var recursiveCall = evaluateWhile(exp, workerScript);
recursiveCall.then(function(foo) {
resolve("endWhileLoop");
}, function(e) { }, function(e) {
reject(e); return Promise.reject(e);
}); });
}, function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
}); });
} else { } else {
resolve("endWhileLoop"); //Doesn't need to resolve to any particular value return Promise.resolve("endWhileLoop"); //Doesn't need to resolve to any particular value
} }
}, function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
});
}); });
} }
function evaluateProg(exp, workerScript, index) { function evaluateProg(exp, workerScript, index) {
var env = workerScript.env; var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);}
return new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript); return;}
if (index >= exp.body.length) { if (index >= exp.body.length) {
resolve("progFinished"); return Promise.resolve("progFinished");
} else { } else {
//Evaluate this line of code in the prog //Evaluate this line of code in the prog
var code = new Promise(function(resolve, reject) {
setTimeout(function() {
var evaluatePromise = evaluate(exp.body[index], workerScript);
evaluatePromise.then(function(evalRes) {
resolve(evalRes);
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
});
//After the code finishes evaluating, evaluate the next line recursively //After the code finishes evaluating, evaluate the next line recursively
code.then(function(codeRes) { return evaluate(exp.body[index], workerScript).then(function(res) {
var nextLine = evaluateProg(exp, workerScript, index + 1); return evaluateProg(exp, workerScript, index + 1);
nextLine.then(function(nextLineRes) { }).then(function(res) {
resolve(workerScript); return Promise.resolve(workerScript);
}, function(e) { }).catch(function(e) {
reject(e); return Promise.reject(e);
});
}, function(e) {
reject(e);
}); });
} }
}); }
function killNetscriptDelay(workerScript) {
if (workerScript instanceof WorkerScript) {
if (workerScript.delay) {
workerScript.delay.cancel();
}
}
} }
function netscriptDelay(time, workerScript) { function netscriptDelay(time, workerScript) {
return new Promise(function(resolve) { var delay = Promise.delay(time, true);
var delay = setTimeout(resolve, time); workerScript.delay = delay;
workerScript.killTrigger = function() { return delay;
clearTimeout(delay);
resolve();
};
});
} }
function makeRuntimeRejectMsg(workerScript, msg) { function makeRuntimeRejectMsg(workerScript, msg) {
@ -885,4 +797,4 @@ export {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript,
scriptCalculateHackingChance, scriptCalculateHackingTime, scriptCalculateHackingChance, scriptCalculateHackingTime,
scriptCalculateExpGain, scriptCalculatePercentMoneyHacked, scriptCalculateExpGain, scriptCalculatePercentMoneyHacked,
scriptCalculateGrowTime, scriptCalculateWeakenTime, evaluate, scriptCalculateGrowTime, scriptCalculateWeakenTime, evaluate,
isScriptErrorMessage}; isScriptErrorMessage, killNetscriptDelay};

@ -30,6 +30,7 @@ import {getCostOfNextHacknetNode,
purchaseHacknet} from "./HacknetNode.js"; purchaseHacknet} from "./HacknetNode.js";
import {Locations} from "./Location.js"; import {Locations} from "./Location.js";
import {Message, Messages} from "./Message.js"; import {Message, Messages} from "./Message.js";
import {inMission} from "./Missions.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {Script, findRunningScript, RunningScript} from "./Script.js"; import {Script, findRunningScript, RunningScript} from "./Script.js";
import {Server, getServer, AddToAllServers, import {Server, getServer, AddToAllServers,
@ -59,6 +60,9 @@ import {dialogBoxCreate} from "../utils/DialogBox.js"
import {printArray, powerOfTwo} from "../utils/HelperFunctions.js"; import {printArray, powerOfTwo} from "../utils/HelperFunctions.js";
import {createRandomIp} from "../utils/IPAddress.js"; import {createRandomIp} from "../utils/IPAddress.js";
import {formatNumber, isString, isHTML} from "../utils/StringHelperFunctions.js"; import {formatNumber, isString, isHTML} from "../utils/StringHelperFunctions.js";
import {yesNoBoxClose, yesNoBoxGetYesButton,
yesNoBoxGetNoButton, yesNoBoxCreate,
yesNoBoxOpen} from "../utils/YesNoBox.js";
var hasSingularitySF=false, hasAISF=false, hasBn11SF=false, hasWallStreetSF=false; var hasSingularitySF=false, hasAISF=false, hasBn11SF=false, hasWallStreetSF=false;
var singularitySFLvl=1, wallStreetSFLvl=1; var singularitySFLvl=1, wallStreetSFLvl=1;
@ -1346,15 +1350,22 @@ function NetscriptFunctions(workerScript) {
getTimeSinceLastAug : function() { getTimeSinceLastAug : function() {
return Player.playtimeSinceLastAug; return Player.playtimeSinceLastAug;
}, },
confirm : function(txt) {
},
/* Singularity Functions */ /* Singularity Functions */
universityCourse(universityName, className) { universityCourse : function(universityName, className) {
if (Player.bitNodeN != 4) { if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 1)) { if (!(hasSingularitySF && singularitySFLvl >= 1)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run universityCourse(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); throw makeRuntimeRejectMsg(workerScript, "Cannot run universityCourse(). It is a Singularity Function and requires SourceFile-4 (level 1) to run.");
return false; return false;
} }
} }
if (inMission) {
workerScript.scriptRef.log("ERROR: universityCourse() failed because you are in the middle of a mission.");
return;
}
if (Player.isWorking) { if (Player.isWorking) {
var txt = Player.singularityStopWork(); var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt); workerScript.scriptRef.log(txt);
@ -1423,13 +1434,17 @@ function NetscriptFunctions(workerScript) {
return true; return true;
}, },
gymWorkout(gymName, stat) { gymWorkout : function(gymName, stat) {
if (Player.bitNodeN != 4) { if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 1)) { if (!(hasSingularitySF && singularitySFLvl >= 1)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run gymWorkout(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); throw makeRuntimeRejectMsg(workerScript, "Cannot run gymWorkout(). It is a Singularity Function and requires SourceFile-4 (level 1) to run.");
return false; return false;
} }
} }
if (inMission) {
workerScript.scriptRef.log("ERROR: universityCourse() failed because you are in the middle of a mission.");
return;
}
if (Player.isWorking) { if (Player.isWorking) {
var txt = Player.singularityStopWork(); var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt); workerScript.scriptRef.log(txt);
@ -1757,6 +1772,11 @@ function NetscriptFunctions(workerScript) {
} }
} }
if (inMission) {
workerScript.scriptRef.log("ERROR: universityCourse() failed because you are in the middle of a mission.");
return;
}
if (Player.companyPosition == "" || !(Player.companyPosition instanceof CompanyPosition)) { if (Player.companyPosition == "" || !(Player.companyPosition instanceof CompanyPosition)) {
workerScript.scriptRef.log("ERROR: workForCompany() failed because you do not have a job"); workerScript.scriptRef.log("ERROR: workForCompany() failed because you do not have a job");
return false; return false;
@ -1910,6 +1930,11 @@ function NetscriptFunctions(workerScript) {
} }
} }
if (inMission) {
workerScript.scriptRef.log("ERROR: universityCourse() failed because you are in the middle of a mission.");
return;
}
if (!factionExists(name)) { if (!factionExists(name)) {
workerScript.scriptRef.log("ERROR: Faction specified in workForFaction() does not exist."); workerScript.scriptRef.log("ERROR: Faction specified in workForFaction() does not exist.");
return false; return false;
@ -2005,7 +2030,10 @@ function NetscriptFunctions(workerScript) {
return false; return false;
} }
} }
if (inMission) {
workerScript.scriptRef.log("ERROR: universityCourse() failed because you are in the middle of a mission.");
return;
}
if (Player.isWorking) { if (Player.isWorking) {
var txt = Player.singularityStopWork(); var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt); workerScript.scriptRef.log(txt);
@ -2085,14 +2113,17 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("Began creating program: " + name); workerScript.scriptRef.log("Began creating program: " + name);
return true; return true;
}, },
commitCrime(crime) { commitCrime : function(crime) {
if (Player.bitNodeN != 4) { if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 3)) { if (!(hasSingularitySF && singularitySFLvl >= 3)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run commitCrime(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); throw makeRuntimeRejectMsg(workerScript, "Cannot run commitCrime(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
return; return;
} }
} }
if (inMission) {
workerScript.scriptRef.log("ERROR: universityCourse() failed because you are in the middle of a mission.");
return;
}
if (Player.isWorking) { if (Player.isWorking) {
var txt = Player.singularityStopWork(); var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt); workerScript.scriptRef.log(txt);

@ -4,7 +4,8 @@ import {addActiveScriptsItem,
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {Environment} from "./NetscriptEnvironment.js"; import {Environment} from "./NetscriptEnvironment.js";
import {evaluate, isScriptErrorMessage} from "./NetscriptEvaluator.js"; import {evaluate, isScriptErrorMessage,
killNetscriptDelay} from "./NetscriptEvaluator.js";
import {AllServers} from "./Server.js"; import {AllServers} from "./Server.js";
import {Settings} from "./Settings.js"; import {Settings} from "./Settings.js";
@ -24,7 +25,8 @@ function WorkerScript(runningScriptObj) {
this.scriptRef = runningScriptObj; this.scriptRef = runningScriptObj;
this.errorMessage = ""; this.errorMessage = "";
this.args = runningScriptObj.args; this.args = runningScriptObj.args;
this.killTrigger = function() {}; //CB func used to clear any delays (netscriptDelay()) //this.killTrigger = function() {}; //CB func used to clear any delays (netscriptDelay())
this.delay = null;
this.fnWorker = null; //Workerscript for a function call this.fnWorker = null; //Workerscript for a function call
} }
@ -93,7 +95,7 @@ function runScriptsLoop() {
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) { if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
try { try {
var ast = parse(workerScripts[i].code); var ast = parse(workerScripts[i].code);
//console.log(ast); console.log(ast);
} catch (e) { } catch (e) {
console.log("Error parsing script: " + workerScripts[i].name); console.log("Error parsing script: " + workerScripts[i].name);
dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e); dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e);
@ -110,8 +112,8 @@ function runScriptsLoop() {
w.running = false; w.running = false;
w.env.stopFlag = true; w.env.stopFlag = true;
w.scriptRef.log("Script finished running"); w.scriptRef.log("Script finished running");
}, function(w) { }).catch(function(w) {
//console.log(w); console.log(w);
if (w instanceof Error) { if (w instanceof Error) {
dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer"); dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer");
console.log("ERROR: Evaluating workerscript returns an Error. THIS SHOULDN'T HAPPEN: " + w.toString()); console.log("ERROR: Evaluating workerscript returns an Error. THIS SHOULDN'T HAPPEN: " + w.toString());
@ -165,11 +167,16 @@ function killWorkerScript(runningScriptObj, serverIp) {
if (workerScripts[i].name == runningScriptObj.filename && workerScripts[i].serverIp == serverIp && if (workerScripts[i].name == runningScriptObj.filename && workerScripts[i].serverIp == serverIp &&
compareArrays(workerScripts[i].args, runningScriptObj.args)) { compareArrays(workerScripts[i].args, runningScriptObj.args)) {
workerScripts[i].env.stopFlag = true; workerScripts[i].env.stopFlag = true;
workerScripts[i].killTrigger(); killNetscriptDelay(workerScripts[i]);
if (workerScripts[i].fnWorker) {
workerScripts[i].fnWorker.env.stopFlag = true;
killNetscriptDelay(workerScripts[i].fnWorker);
}
/*workerScripts[i].killTrigger();
if (workerScripts[i].fnWorker) { if (workerScripts[i].fnWorker) {
workerScripts[i].fnWorker.env.stopFlag = true; workerScripts[i].fnWorker.env.stopFlag = true;
workerScripts[i].fnWorker.killTrigger(); workerScripts[i].fnWorker.killTrigger();
} }*/
return true; return true;
} }
} }

@ -367,7 +367,7 @@ function initStockMarket() {
StockMarket[joesguns] = joesgunsStk; StockMarket[joesguns] = joesgunsStk;
var catalyst = "Catalyst Ventures"; var catalyst = "Catalyst Ventures";
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.6, true, 20, getRandomInt(500, 1000)); var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.6, true, 15, getRandomInt(500, 1000));
StockMarket[catalyst] = catalystStk; StockMarket[catalyst] = catalystStk;
var microdyne = "Microdyne Technologies"; var microdyne = "Microdyne Technologies";
@ -408,8 +408,8 @@ function stockMarketCycle() {
for (var name in StockMarket) { for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) { if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name]; var stock = StockMarket[name];
var thresh = 0.6; var thresh = 0.59;
if (stock.b) {thresh = 0.4;} if (stock.b) {thresh = 0.41;}
if (Math.random() < thresh) { if (Math.random() < thresh) {
stock.b = !stock.b; stock.b = !stock.b;
} }
@ -832,6 +832,8 @@ function createStockTicker(stock) {
orderTypeSelect = document.createElement("select"), orderTypeSelect = document.createElement("select"),
buyButton = document.createElement("span"), buyButton = document.createElement("span"),
sellButton = document.createElement("span"), sellButton = document.createElement("span"),
buyMaxButton = document.createElement("span"),
sellAllButton = document.createElement("span"),
positionTxt = document.createElement("p"), positionTxt = document.createElement("p"),
orderList = document.createElement("ul"); orderList = document.createElement("ul");
@ -952,6 +954,76 @@ function createStockTicker(stock) {
return false; return false;
}); });
buyMaxButton.classList.add("stock-market-input");
buyMaxButton.classList.add("a-link-button");
buyMaxButton.innerHTML = "Buy MAX";
buyMaxButton.addEventListener("click", ()=>{
var pos = longShortSelect.options[longShortSelect.selectedIndex].text;
pos === "Long" ? pos = PositionTypes.Long : pos = PositionTypes.Short;
var ordType = orderTypeSelect.options[orderTypeSelect.selectedIndex].text;
var money = Player.money.toMoney();
switch (ordType) {
case "Market Order":
var shares = Math.floor(money / stock.price);
pos === PositionTypes.Long ? buyStock(stock, shares) : shortStock(stock, shares, null);
break;
case "Limit Order":
case "Stop Order":
var yesBtn = yesNoTxtInpBoxGetYesButton(),
noBtn = yesNoTxtInpBoxGetNoButton();
yesBtn.innerText = "Place Buy " + ordType;
noBtn.innerText = "Cancel Order";
yesBtn.addEventListener("click", ()=>{
var price = Number(yesNoTxtInpBoxGetInput()), type;
if (ordType === "Limit Order") {
type = OrderTypes.LimitBuy;
} else {
type = OrderTypes.StopBuy;
}
var shares = Math.floor(money / price);
placeOrder(stock, shares, price, type, pos);
yesNoTxtInpBoxClose();
});
noBtn.addEventListener("click", ()=>{
yesNoTxtInpBoxClose();
});
yesNoTxtInpBoxCreate("Enter the price for your " + ordType);
break;
default:
console.log("ERROR: Invalid order type");
break;
}
return false;
});
sellAllButton.classList.add("stock-market-input");
sellAllButton.classList.add("a-link-button");
sellAllButton.innerHTML = "Sell ALL";
sellAllButton.addEventListener("click", ()=>{
var pos = longShortSelect.options[longShortSelect.selectedIndex].text;
pos === "Long" ? pos = PositionTypes.Long : pos = PositionTypes.Short;
var ordType = orderTypeSelect.options[orderTypeSelect.selectedIndex].text;
switch (ordType) {
case "Market Order":
if (pos === PositionTypes.Long) {
var shares = stock.playerShares;
sellStock(stock, shares);
} else {
var shares = stock.playerShortShares;
sellShort(stock, shares, null);
}
break;
case "Limit Order":
case "Stop Order":
dialogBoxCreate("ERROR: 'Sell All' only works for Market Orders")
break;
default:
console.log("ERROR: Invalid order type");
break;
}
return false;
});
positionTxt.setAttribute("id", tickerId + "-position-text"); positionTxt.setAttribute("id", tickerId + "-position-text");
positionTxt.classList.add("stock-market-position-text"); positionTxt.classList.add("stock-market-position-text");
stock.posTxtEl = positionTxt; stock.posTxtEl = positionTxt;
@ -964,6 +1036,8 @@ function createStockTicker(stock) {
stockDiv.appendChild(orderTypeSelect); stockDiv.appendChild(orderTypeSelect);
stockDiv.appendChild(buyButton); stockDiv.appendChild(buyButton);
stockDiv.appendChild(sellButton); stockDiv.appendChild(sellButton);
stockDiv.appendChild(buyMaxButton);
stockDiv.appendChild(sellAllButton);
stockDiv.appendChild(positionTxt); stockDiv.appendChild(positionTxt);
stockDiv.appendChild(orderList); stockDiv.appendChild(orderList);

@ -22,6 +22,7 @@ function yesNoBoxGetNoButton() {
} }
function yesNoBoxCreate(txt) { function yesNoBoxCreate(txt) {
if (yesNoBoxOpen) {return false;} //Already open
yesNoBoxOpen = true; yesNoBoxOpen = true;
var textElement = document.getElementById("yes-no-box-text"); var textElement = document.getElementById("yes-no-box-text");
if (textElement) { if (textElement) {
@ -34,6 +35,7 @@ function yesNoBoxCreate(txt) {
} else { } else {
console.log("ERROR: Container not found for YesNoBox"); console.log("ERROR: Container not found for YesNoBox");
} }
return true;
} }
/* Generic Yes-No POp-up Box with Text input */ /* Generic Yes-No POp-up Box with Text input */