From 013af4e26cd96f79004760abad58a7d7f733d117 Mon Sep 17 00:00:00 2001 From: danielyxie Date: Tue, 30 Oct 2018 16:02:16 -0500 Subject: [PATCH] Refactored Stock market to store/accumulate cycles so that it's not completely useless when offline/tabbed out --- src/Constants.js | 42 ++++------------ src/NetscriptFunctions.js | 7 ++- src/Stock.ts | 7 +++ src/StockMarket.js | 100 ++++++++++++++++++++++---------------- src/engine.js | 15 +++--- 5 files changed, 85 insertions(+), 86 deletions(-) diff --git a/src/Constants.js b/src/Constants.js index 760b1f394..7b68332d4 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -502,38 +502,16 @@ let CONSTANTS = { LatestUpdate: ` - v0.41.0 - * WARNING: In NetscriptJS, defining a function called print() is no longer possible - * Gang Mechanic Changes (BitNode-2): - *** Added a Gang Netscript API - *** Added new 'ascension' mechanic for Gang Members - *** The first three gang members are now 'free' (can be recruited instantly) - *** Maximum number of increased Gang Members increased from 20 to 30 - *** Changed the formula for calculating respect needed to recruit the next gang member - *** Added a new category of upgrades for Gang Members: Augmentations - *** Non-Augmentation Gang member upgrades are now significantly weaker - *** Reputation for your Gang faction can no longer be gained through Infiltration - *** Re-worked the territory 'warfare' mechanic so that player can choose when to engage in it - *** Gang Members can now be killed during territory 'warfare' - *** Changed BitNode-2 Multipliers to make hacking slightly less profitable - *** Gang Member Equipment + Upgrades now get cheaper as your gang grows in power and respect - *** The effects of Source-File 2 are now slightly more powerful - * RAM Cost of accessing the global document object lowered from 100 GB to 25 GB - * RAM Cost to use Singularity Functions outside of BitNode-4 lowered by 75%. They now only cost twice as much as they do in BitNode-4 - * b1t_flum3.exe now takes significantly less time to create - * Crimes commited through Singularity function no longer give half money/exp - * Improved number formatting for Player 'work' actions (including crimes, etc.). These numbers should also adhere to locale settings now (by Kline-) - * The order that Augmentations are listed in (when purchasing from Faction and viewing your Augmentations) is now saved and persists when choosing different orders - * getCharacterInformation() Singularity function now returns multiplier information (from Augmentations/Source Files) - * Bug Fix: Calling print() in NetscriptJS no longer brings up the print dialog - * Bug Fix: Fixed a bug that sometimes caused a blank black screen when destroying/resetting/switching BitNodes - * Bug Fix: Netscript calls that throw errors will now no longer cause the 'concurrent calls' error if they are caught in the script. i.e. try/catch should now work properly in scripts - * Bug Fix: Fixed a bug where sometimes the NeuroFlux Governor Augmentation level would be incorrectly calculated when the game was loaded - * Bug Fix: Fixed a bug where calling the scp() Netscript function with invalid hostname/ips would throw an unclear error message - * Bug Fix: Bladeburner API function getActionCountRemaining() should now work properly for BlackOps - * Bug Fix: Black Ops can no longer be attempted out-of-order or without the required rank via Bladeburner API - * Bug Fix: Dynamic RAM Calculation now properly accounts for number of threads - * RAM cost for basic Netscript functions added to documentation (by CBJamo) + v0.41.1 + * Stock Market changes: + *** Stocks now have "maximum prices" + *** If a stock reaches its "maximum price", it will most likely drop in value (although it might still rise) + *** Each stock has its own, unique maximum price + *** Maximum price for each stock are randomly generated and change during each 'reset' + *** Stock Market cycles are now accumulated/stored, much like it is for Gangs and Bladeburners + *** Accumulated/stored cycles cause stock prices to update up to 50% faster (from every 6 seconds to 4 seconds) + ****** This means that after coming back from being offline, stock prices will update faster to make up for offline time + ` } diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 4c8003613..bc9d7df18 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -35,10 +35,9 @@ import {Server, getServer, AddToAllServers, import {Settings} from "./Settings"; import {SpecialServerIps} from "./SpecialServerIps"; import {Stock} from "./Stock"; -import {StockMarket, StockSymbols, SymbolToStockMap, initStockSymbols, - initStockMarket, initSymbolToStockMap, stockMarketCycle, buyStock, - sellStock, updateStockPrices, displayStockMarketContent, - updateStockTicker, updateStockPlayerPosition, +import {StockMarket, StockSymbols, SymbolToStockMap, + initStockMarket, initSymbolToStockMap, buyStock, + sellStock, updateStockPlayerPosition, shortStock, sellShort, OrderTypes, PositionTypes, placeOrder, cancelOrder} from "./StockMarket"; import {post} from "./ui/postToTerminal"; diff --git a/src/Stock.ts b/src/Stock.ts index 2ece32cf3..05139cdaa 100644 --- a/src/Stock.ts +++ b/src/Stock.ts @@ -1,4 +1,5 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver"; +import { getRandomInt } from "../utils/helpers/getRandomInt"; /** * Represents the valuation of a company in the World Stock Exchange. @@ -16,6 +17,11 @@ export class Stock { */ b: boolean; + /** + * Maximum price of a stock (per share) + */ + readonly cap: number; + /** * Maximum volatility */ @@ -83,6 +89,7 @@ export class Stock { this.mv = mv; this.b = b; this.otlkMag = otlkMag; + this.cap = getRandomInt(initPrice * 1e3, initPrice * 25e3); this.posTxtEl = null; } diff --git a/src/StockMarket.js b/src/StockMarket.js index 913606b3c..78d21dc67 100755 --- a/src/StockMarket.js +++ b/src/StockMarket.js @@ -23,8 +23,6 @@ import {yesNoBoxCreate, yesNoTxtInpBoxCreate, yesNoTxtInpBoxGetInput, yesNoBoxClose, yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox"; -let StockPriceCap = 1e9; //Put a limit on how high a price can go - var OrderTypes = { LimitBuy: "Limit Buy Order", LimitSell: "Limit Sell Order", @@ -227,136 +225,138 @@ function initStockMarket() { } } + const randInt = getRandomInt; + var ecorp = Locations.AevumECorp; - var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], getRandomInt(40, 50)/100, true, 19, getRandomInt(17e3, 28e3)); + var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], randInt(40, 50) / 100, true, 19, randInt(17e3, 28e3)); StockMarket[ecorp] = ecorpStk; var megacorp = Locations.Sector12MegaCorp; - var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], getRandomInt(40,50)/100, true, 19, getRandomInt(24e3, 34e3)); + var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], randInt(40,50)/100, true, 19, randInt(24e3, 34e3)); StockMarket[megacorp] = megacorpStk; var blade = Locations.Sector12BladeIndustries; - var bladeStk = new Stock(blade, StockSymbols[blade], getRandomInt(70, 80)/100, true, 13, getRandomInt(12e3, 25e3)); + var bladeStk = new Stock(blade, StockSymbols[blade], randInt(70, 80)/100, true, 13, randInt(12e3, 25e3)); StockMarket[blade] = bladeStk; var clarke = Locations.AevumClarkeIncorporated; - var clarkeStk = new Stock(clarke, StockSymbols[clarke], getRandomInt(65, 75)/100, true, 12, getRandomInt(10e3, 25e3)); + var clarkeStk = new Stock(clarke, StockSymbols[clarke], randInt(65, 75)/100, true, 12, randInt(10e3, 25e3)); StockMarket[clarke] = clarkeStk; var omnitek = Locations.VolhavenOmniTekIncorporated; - var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], getRandomInt(60, 70)/100, true, 12, getRandomInt(32e3, 43e3)); + var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], randInt(60, 70)/100, true, 12, randInt(32e3, 43e3)); StockMarket[omnitek] = omnitekStk; var foursigma = Locations.Sector12FourSigma; - var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], getRandomInt(100, 110)/100, true, 17, getRandomInt(50e3, 80e3)); + var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], randInt(100, 110)/100, true, 17, randInt(50e3, 80e3)); StockMarket[foursigma] = foursigmaStk; var kuaigong = Locations.ChongqingKuaiGongInternational; - var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], getRandomInt(75, 85)/100, true, 10, getRandomInt(16e3, 28e3)); + var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], randInt(75, 85)/100, true, 10, randInt(16e3, 28e3)); StockMarket[kuaigong] = kuaigongStk; var fulcrum = Locations.AevumFulcrumTechnologies; - var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], getRandomInt(120, 130)/100, true, 16, getRandomInt(29e3, 36e3)); + var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], randInt(120, 130)/100, true, 16, randInt(29e3, 36e3)); StockMarket[fulcrum] = fulcrumStk; var storm = Locations.IshimaStormTechnologies; - var stormStk = new Stock(storm, StockSymbols[storm], getRandomInt(80, 90)/100, true, 7, getRandomInt(20e3, 25e3)); + var stormStk = new Stock(storm, StockSymbols[storm], randInt(80, 90)/100, true, 7, randInt(20e3, 25e3)); StockMarket[storm] = stormStk; var defcomm = Locations.NewTokyoDefComm; - var defcommStk = new Stock(defcomm, StockSymbols[defcomm], getRandomInt(60, 70)/100, true, 10, getRandomInt(6e3, 19e3)); + var defcommStk = new Stock(defcomm, StockSymbols[defcomm], randInt(60, 70)/100, true, 10, randInt(6e3, 19e3)); StockMarket[defcomm] = defcommStk; var helios = Locations.VolhavenHeliosLabs; - var heliosStk = new Stock(helios, StockSymbols[helios], getRandomInt(55, 65)/100, true, 9, getRandomInt(10e3, 18e3)); + var heliosStk = new Stock(helios, StockSymbols[helios], randInt(55, 65)/100, true, 9, randInt(10e3, 18e3)); StockMarket[helios] = heliosStk; var vitalife = Locations.NewTokyoVitaLife; - var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], getRandomInt(70, 80)/100, true, 7, getRandomInt(8e3, 14e3)); + var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], randInt(70, 80)/100, true, 7, randInt(8e3, 14e3)); StockMarket[vitalife] = vitalifeStk; var icarus = Locations.Sector12IcarusMicrosystems; - var icarusStk = new Stock(icarus, StockSymbols[icarus], getRandomInt(60, 70)/100, true, 7.5, getRandomInt(12e3, 24e3)); + var icarusStk = new Stock(icarus, StockSymbols[icarus], randInt(60, 70)/100, true, 7.5, randInt(12e3, 24e3)); StockMarket[icarus] = icarusStk; var universalenergy = Locations.Sector12UniversalEnergy; - var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], getRandomInt(50, 60)/100, true, 10, getRandomInt(16e3, 29e3)); + var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], randInt(50, 60)/100, true, 10, randInt(16e3, 29e3)); StockMarket[universalenergy] = universalenergyStk; var aerocorp = Locations.AevumAeroCorp; - var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], getRandomInt(55, 65)/100, true, 6, getRandomInt(8e3, 17e3)); + var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], randInt(55, 65)/100, true, 6, randInt(8e3, 17e3)); StockMarket[aerocorp] = aerocorpStk; var omnia = Locations.VolhavenOmniaCybersystems; - var omniaStk = new Stock(omnia, StockSymbols[omnia], getRandomInt(65, 75)/100, true, 4.5, getRandomInt(6e3, 15e3)); + var omniaStk = new Stock(omnia, StockSymbols[omnia], randInt(65, 75)/100, true, 4.5, randInt(6e3, 15e3)); StockMarket[omnia] = omniaStk; var solaris = Locations.ChongqingSolarisSpaceSystems; - var solarisStk = new Stock(solaris, StockSymbols[solaris], getRandomInt(70, 80)/100, true, 8.5, getRandomInt(14e3, 28e3)); + var solarisStk = new Stock(solaris, StockSymbols[solaris], randInt(70, 80)/100, true, 8.5, randInt(14e3, 28e3)); StockMarket[solaris] = solarisStk; var globalpharm = Locations.NewTokyoGlobalPharmaceuticals; - var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], getRandomInt(55, 65)/100, true, 10.5, getRandomInt(12e3, 30e3)); + var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], randInt(55, 65)/100, true, 10.5, randInt(12e3, 30e3)); StockMarket[globalpharm] = globalpharmStk; var nova = Locations.IshimaNovaMedical; - var novaStk = new Stock(nova, StockSymbols[nova], getRandomInt(70, 80)/100, true, 5, getRandomInt(15e3, 27e3)); + var novaStk = new Stock(nova, StockSymbols[nova], randInt(70, 80)/100, true, 5, randInt(15e3, 27e3)); StockMarket[nova] = novaStk; var watchdog = Locations.AevumWatchdogSecurity; - var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], getRandomInt(240, 260)/100, true, 1.5, getRandomInt(4e3, 8.5e3)); + var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], randInt(240, 260)/100, true, 1.5, randInt(4e3, 8.5e3)); StockMarket[watchdog] = watchdogStk; var lexocorp = Locations.VolhavenLexoCorp; - var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], getRandomInt(115, 135)/100, true, 6, getRandomInt(4.5e3, 8e3)); + var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], randInt(115, 135)/100, true, 6, randInt(4.5e3, 8e3)); StockMarket[lexocorp] = lexocorpStk; var rho = Locations.AevumRhoConstruction; - var rhoStk = new Stock(rho, StockSymbols[rho], getRandomInt(50, 70)/100, true, 1, getRandomInt(2e3, 7e3)); + var rhoStk = new Stock(rho, StockSymbols[rho], randInt(50, 70)/100, true, 1, randInt(2e3, 7e3)); StockMarket[rho] = rhoStk; var alpha = Locations.Sector12AlphaEnterprises; - var alphaStk = new Stock(alpha, StockSymbols[alpha], getRandomInt(175, 205)/100, true, 10, getRandomInt(4e3, 8.5e3)); + var alphaStk = new Stock(alpha, StockSymbols[alpha], randInt(175, 205)/100, true, 10, randInt(4e3, 8.5e3)); StockMarket[alpha] = alphaStk; var syscore = Locations.VolhavenSysCoreSecurities; - var syscoreStk = new Stock(syscore, StockSymbols[syscore], getRandomInt(150, 170)/100, true, 3, getRandomInt(3e3, 8e3)); + var syscoreStk = new Stock(syscore, StockSymbols[syscore], randInt(150, 170)/100, true, 3, randInt(3e3, 8e3)); StockMarket[syscore] = syscoreStk; var computek = Locations.VolhavenCompuTek; - var computekStk = new Stock(computek, StockSymbols[computek], getRandomInt(80, 100)/100, true, 4, getRandomInt(1e3, 6e3)); + var computekStk = new Stock(computek, StockSymbols[computek], randInt(80, 100)/100, true, 4, randInt(1e3, 6e3)); StockMarket[computek] = computekStk; var netlink = Locations.AevumNetLinkTechnologies; - var netlinkStk = new Stock(netlink, StockSymbols[netlink], getRandomInt(400, 430)/100, true, 1, getRandomInt(1e3, 5e3)); + var netlinkStk = new Stock(netlink, StockSymbols[netlink], randInt(400, 430)/100, true, 1, randInt(1e3, 5e3)); StockMarket[netlink] = netlinkStk; var omega = Locations.IshimaOmegaSoftware; - var omegaStk = new Stock(omega, StockSymbols[omega], getRandomInt(90, 110)/100, true, 0.5, getRandomInt(1e3, 8e3)); + var omegaStk = new Stock(omega, StockSymbols[omega], randInt(90, 110)/100, true, 0.5, randInt(1e3, 8e3)); StockMarket[omega] = omegaStk; var fns = Locations.Sector12FoodNStuff; - var fnsStk = new Stock(fns, StockSymbols[fns], getRandomInt(70, 80)/100, false, 1, getRandomInt(500, 4.5e3)); + var fnsStk = new Stock(fns, StockSymbols[fns], randInt(70, 80)/100, false, 1, randInt(500, 4.5e3)); StockMarket[fns] = fnsStk; var sigmacosm = "Sigma Cosmetics"; - var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], getRandomInt(260, 300)/100, true, 0, getRandomInt(1.5e3, 3.5e3)); + var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], randInt(260, 300)/100, true, 0, randInt(1.5e3, 3.5e3)); StockMarket[sigmacosm] = sigmacosmStk; var joesguns = "Joes Guns"; - var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], getRandomInt(360, 400)/100, true, 1, getRandomInt(250, 1.5e3)); + var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], randInt(360, 400)/100, true, 1, randInt(250, 1.5e3)); StockMarket[joesguns] = joesgunsStk; var catalyst = "Catalyst Ventures"; - var catalystStk = new Stock(catalyst, StockSymbols[catalyst], getRandomInt(120, 175)/100, true, 13.5, getRandomInt(250, 1.5e3)); + var catalystStk = new Stock(catalyst, StockSymbols[catalyst], randInt(120, 175)/100, true, 13.5, randInt(250, 1.5e3)); StockMarket[catalyst] = catalystStk; var microdyne = "Microdyne Technologies"; - var microdyneStk = new Stock(microdyne, StockSymbols[microdyne], getRandomInt(70, 80)/100, true, 8, getRandomInt(15e3, 30e3)); + var microdyneStk = new Stock(microdyne, StockSymbols[microdyne], randInt(70, 80)/100, true, 8, randInt(15e3, 30e3)); StockMarket[microdyne] = microdyneStk; var titanlabs = "Titan Laboratories"; - var titanlabsStk = new Stock(titanlabs, StockSymbols[titanlabs], getRandomInt(50, 70)/100, true, 11, getRandomInt(12e3, 24e3)); + var titanlabsStk = new Stock(titanlabs, StockSymbols[titanlabs], randInt(50, 70)/100, true, 11, randInt(12e3, 24e3)); StockMarket[titanlabs] = titanlabsStk; var orders = {}; @@ -368,6 +368,9 @@ function initStockMarket() { } } StockMarket["Orders"] = orders; + + StockMarket.storedCycles = 0; + StockMarket.lastUpdate = 0; } function initSymbolToStockMap() { @@ -375,7 +378,7 @@ function initSymbolToStockMap() { if (StockSymbols.hasOwnProperty(name)) { var stock = StockMarket[name]; if (stock == null) { - console.log("ERROR finding stock"); + console.error(`Could not find Stock for ${name}`); continue; } var symbol = StockSymbols[name]; @@ -543,12 +546,27 @@ function sellShort(stock, shares, workerScript=null) { return true; } -function updateStockPrices() { +function processStockPrices(numCycles=1) { + if (isNaN(StockMarket.storedCycles)) { StockMarket.storedCycles = 0; } + StockMarket.storedCycles += numCycles; + + // Stock Prices updated every 6 seconds on average. But if there are stored + // cycles they update 50% faster, so every 4 seconds + const msPerStockUpdate = 6e3; + const cyclesPerStockUpdate = msPerStockUpdate / CONSTANTS.MilliPerCycle; + if (StockMarket.storedCycles < cyclesPerStockUpdate) { return; } + + const timeNow = new Date().getTime(); + if (timeNow - StockMarket.lastUpdate < 4e3) { return; } + + StockMarket.lastUpdate = timeNow; + StockMarket.storedCycles -= cyclesPerStockUpdate; + var v = Math.random(); for (var name in StockMarket) { if (StockMarket.hasOwnProperty(name)) { var stock = StockMarket[name]; - if (!(stock instanceof Stock)) {continue;} + if (!(stock instanceof Stock)) { continue; } var av = (v * stock.mv) / 100; if (isNaN(av)) {av = .02;} @@ -560,8 +578,8 @@ function updateStockPrices() { chc = (chc - stock.otlkMag)/100; if (isNaN(chc)) {chc = 0.5;} } - if (stock.price >= StockPriceCap) { - chc = -1; //Limit on stock price + if (stock.price >= stock.cap) { + chc = 0.1; // "Soft Limit" on stock price. It could still go up but its unlikely stock.b = false; } @@ -1459,6 +1477,6 @@ function updateStockOrderList(stock) { export {StockMarket, StockSymbols, SymbolToStockMap, initStockSymbols, initStockMarket, initSymbolToStockMap, stockMarketCycle, buyStock, - sellStock, shortStock, sellShort, updateStockPrices, displayStockMarketContent, + sellStock, shortStock, sellShort, processStockPrices, displayStockMarketContent, updateStockTicker, updateStockPlayerPosition, loadStockMarket, setStockMarketContentCreated, placeOrder, cancelOrder, Order, OrderTypes, PositionTypes}; diff --git a/src/engine.js b/src/engine.js index cd565de26..19364d6cb 100644 --- a/src/engine.js +++ b/src/engine.js @@ -66,7 +66,7 @@ import {SpecialServerIps, initSpecialServerIps} from "./SpecialServerIps import {StockMarket, StockSymbols, SymbolToStockMap, initStockSymbols, initSymbolToStockMap, stockMarketCycle, - updateStockPrices, + processStockPrices, displayStockMarketContent} from "./StockMarket"; import {Terminal, postNetburnerText} from "./Terminal"; import {KEY} from "../utils/helpers/keyCodes"; @@ -885,6 +885,11 @@ const Engine = { } } + // Update stock prices + if (Player.hasWseAccount) { + processStockPrices(numCycles); + } + //Gang, if applicable if (Player.bitNodeN == 2 && Player.inGang()) { Player.gang.process(numCycles, Player); @@ -935,7 +940,6 @@ const Engine = { checkFactionInvitations: 100, //Check whether you qualify for any faction invitations passiveFactionGrowth: 600, messages: 150, - stockTick: 30, //Update stock prices sCr: 1500, mechanicProcess: 5, //Processes certain mechanics (Corporation, Bladeburner) contractGeneration: 3000 //Generate Coding Contracts @@ -1056,13 +1060,6 @@ const Engine = { } } - if (Engine.Counters.stockTick <= 0) { - if (Player.hasWseAccount) { - updateStockPrices(); - } - Engine.Counters.stockTick = 30; - } - if (Engine.Counters.sCr <= 0) { if (Player.hasWseAccount) { stockMarketCycle();