mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-18 21:53:50 +01:00
write()/read() now work for script files. You can now use angled brackets in tprint() (and create DOM elements). Added CodingContract implementation
This commit is contained in:
parent
ebd8d282ed
commit
c309c0cdc9
203
src/CodingContracts.ts
Normal file
203
src/CodingContracts.ts
Normal file
@ -0,0 +1,203 @@
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc } from "./data/codingcontracttypes";
|
||||
import { IMap } from "./types";
|
||||
|
||||
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
||||
|
||||
/* Represents different types of problems that a Coding Contract can have */
|
||||
export class ContractType {
|
||||
/**
|
||||
* Function that generates a description of the problem
|
||||
*/
|
||||
desc: DescriptionFunc;
|
||||
|
||||
/**
|
||||
* Number that generally represents the problem's difficulty. Bigger numbers = harder
|
||||
*/
|
||||
difficulty: number;
|
||||
|
||||
/**
|
||||
* A function that randomly generates a valid 'data' for the problem
|
||||
*/
|
||||
generate: GeneratorFunc;
|
||||
|
||||
/**
|
||||
* Name of the type of problem
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* The maximum number of tries the player gets on this kind of problem before it self-destructs
|
||||
*/
|
||||
numTries: number;
|
||||
|
||||
/**
|
||||
* Stores a function that checks if the provided answer is correct
|
||||
*/
|
||||
solver: SolverFunc;
|
||||
|
||||
constructor(name: string,
|
||||
desc: DescriptionFunc,
|
||||
gen: GeneratorFunc,
|
||||
solver: SolverFunc,
|
||||
diff: number,
|
||||
numTries: number) {
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.generate = gen;
|
||||
this.solver = solver;
|
||||
this.difficulty = diff;
|
||||
this.numTries = numTries;
|
||||
}
|
||||
}
|
||||
|
||||
/* Contract Types */
|
||||
// tslint:disable-next-line
|
||||
export const ContractTypes: IMap<ContractType> = {};
|
||||
|
||||
for (const md of codingContractTypesMetadata) {
|
||||
ContractTypes[md.name] = new ContractType(md.name, md.desc, md.gen, md.solver, md.difficulty, md.numTries);
|
||||
}
|
||||
console.info(`${Object.keys(ContractTypes).length} Coding Contract Types loaded`);
|
||||
|
||||
/**
|
||||
* Enum representing the different types of rewards a Coding Contract can give
|
||||
*/
|
||||
export enum CodingContractRewardType {
|
||||
FactionReputation,
|
||||
FactionReputationAll,
|
||||
CompanyReputation,
|
||||
Money,
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum representing the result when trying to solve the Contract
|
||||
*/
|
||||
export enum CodingContractResult {
|
||||
Success,
|
||||
Failure,
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that represents the type of reward a contract gives
|
||||
*/
|
||||
export interface ICodingContractReward {
|
||||
/* Name of Company/Faction name for reward, if applicable */
|
||||
name?: string;
|
||||
type: CodingContractRewardType;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Coding Contract is a file that poses a programming-related problem to the Player.
|
||||
* The player receives a reward if the problem is solved correctly
|
||||
*/
|
||||
export class CodingContract {
|
||||
/**
|
||||
* Initiatizes a CodingContract from a JSON save state.
|
||||
*/
|
||||
static fromJSON(value: any): CodingContract {
|
||||
return Generic_fromJSON(CodingContract, value.data);
|
||||
}
|
||||
|
||||
/* Relevant data for the contract's problem */
|
||||
data: any;
|
||||
|
||||
/* Contract's filename */
|
||||
fn: string;
|
||||
|
||||
/* Describes the reward given if this Contract is solved. The reward is actually
|
||||
processed outside of this file */
|
||||
reward: ICodingContractReward | null;
|
||||
|
||||
/* Number of times the Contract has been attempted */
|
||||
tries: number = 0;
|
||||
|
||||
/* String representing the contract's type. Must match type in ContractTypes */
|
||||
type: string;
|
||||
|
||||
constructor(fn: string = "",
|
||||
type: string = "Find Largest Prime Factor",
|
||||
reward: ICodingContractReward | null = null) {
|
||||
this.fn = fn;
|
||||
if (!this.fn.endsWith(".cct")) {
|
||||
this.fn += ".cct";
|
||||
}
|
||||
|
||||
// tslint:disable-next-line
|
||||
if (ContractTypes[type] == null) {
|
||||
throw new Error(`Error: invalid contract type: ${type} please contact developer`);
|
||||
}
|
||||
|
||||
this.type = type;
|
||||
this.data = ContractTypes[type].generate();
|
||||
this.reward = reward;
|
||||
}
|
||||
|
||||
getDifficulty(): number {
|
||||
return ContractTypes[this.type].difficulty;
|
||||
}
|
||||
|
||||
getMaxNumTries(): number {
|
||||
return ContractTypes[this.type].numTries;
|
||||
}
|
||||
|
||||
isSolution(solution: string): boolean {
|
||||
return ContractTypes[this.type].solver(this.data, solution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a popup to prompt the player to solve the problem
|
||||
*/
|
||||
async prompt(): Promise<CodingContractResult> {
|
||||
// tslint:disable-next-line
|
||||
return new Promise<CodingContractResult>((resolve: Function, reject: Function) => {
|
||||
const contractType: ContractType = ContractTypes[this.type];
|
||||
const popupId: string = `coding-contract-prompt-popup-${this.fn}`;
|
||||
const txt: HTMLElement = createElement("p", {
|
||||
innerText: ["You are attempting to solve a Coding Contract. Note that",
|
||||
"you only have one chance. Providing the wrong solution",
|
||||
"will cause the contract to self-destruct.\n\n",
|
||||
`${contractType.desc(this.data)}`].join(" "),
|
||||
});
|
||||
const answerInput: HTMLInputElement = createElement("input", {
|
||||
placeholder: "Enter Solution here",
|
||||
}) as HTMLInputElement;
|
||||
const solveBtn: HTMLElement = createElement("a", {
|
||||
class: "a-link-button",
|
||||
clickListener: () => {
|
||||
const answer: string = answerInput.value;
|
||||
if (this.isSolution(answer)) {
|
||||
resolve(CodingContractResult.Success);
|
||||
} else {
|
||||
resolve(CodingContractResult.Failure);
|
||||
}
|
||||
removeElementById(popupId);
|
||||
},
|
||||
innerText: "Solve",
|
||||
});
|
||||
const cancelBtn: HTMLElement = createElement("a", {
|
||||
class: "a-link-button",
|
||||
clickListener: () => {
|
||||
resolve(CodingContractResult.Cancelled);
|
||||
removeElementById(popupId);
|
||||
},
|
||||
innerText: "Cancel",
|
||||
});
|
||||
const lineBreak: HTMLElement = createElement("br");
|
||||
createPopup(popupId, [txt, lineBreak, lineBreak, answerInput, solveBtn, cancelBtn]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the current file to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
return Generic_toJSON("CodingContract", this);
|
||||
}
|
||||
}
|
||||
|
||||
Reviver.constructors.CodingContract = CodingContract;
|
@ -85,6 +85,8 @@ let CONSTANTS = {
|
||||
ScriptGetScriptRamCost: 0.1,
|
||||
ScriptGetHackTimeRamCost: 0.05,
|
||||
ScriptGetFavorToDonate: 0.10,
|
||||
ScriptGetContractDataRamCost: 25,
|
||||
ScriptAttemptContractRamCost: 25,
|
||||
|
||||
ScriptSingularityFn1RamCost: 1,
|
||||
ScriptSingularityFn2RamCost: 2,
|
||||
@ -191,12 +193,13 @@ let CONSTANTS = {
|
||||
"-Nodes slowly regenerate health over time.",
|
||||
|
||||
|
||||
//Gang constants
|
||||
/* Gang constant */
|
||||
GangRespectToReputationRatio: 2, //Respect is divided by this to get rep gain
|
||||
MaximumGangMembers: 20,
|
||||
GangRecruitCostMultiplier: 2,
|
||||
GangTerritoryUpdateTimer: 150,
|
||||
|
||||
/* Time Constants */
|
||||
MillisecondsPer20Hours: 72000000,
|
||||
GameCyclesPer20Hours: 72000000 / 200,
|
||||
|
||||
@ -224,6 +227,7 @@ let CONSTANTS = {
|
||||
MillisecondsPerFiveMinutes: 300000,
|
||||
GameCyclesPerFiveMinutes: 300000 / 200,
|
||||
|
||||
/* Player Work / Action related Constants */
|
||||
FactionWorkHacking: "Faction Hacking Work",
|
||||
FactionWorkField: "Faction Field Work",
|
||||
FactionWorkSecurity: "Faction Security Work",
|
||||
@ -267,6 +271,11 @@ let CONSTANTS = {
|
||||
CrimeAssassination: "assassinate a high-profile target",
|
||||
CrimeHeist: "pull off the ultimate heist",
|
||||
|
||||
/* Coding Contract Constants */
|
||||
CodingContractBaseFactionRepGain: 2500,
|
||||
CodingContractBaseCompanyRepGain: 4000,
|
||||
CodingContractBaseMoneyGain: 10e6,
|
||||
|
||||
/* Tutorial related things */
|
||||
TutorialNetworkingText: "Servers are a central part of the game. You start with a single personal server (your home computer) " +
|
||||
"and you can purchase additional servers as you progress through the game. Connecting to other servers " +
|
||||
@ -497,7 +506,13 @@ let CONSTANTS = {
|
||||
"World Stock Exchange account and TIX API Access<br>",
|
||||
|
||||
LatestUpdate:
|
||||
`v0.40.3<br>
|
||||
`
|
||||
v0.40.4<br>
|
||||
* (TODO NEEDS DOCUMENTATION) The write() and read() Netscript functions now work on scripts<br>
|
||||
* It is now possible to use freely use angled bracket (<, >) and create DOM elements using tprint()<br>
|
||||
* Added Coding Contracts (not yet generated in game, but the data/implementation exists)<br>
|
||||
|
||||
v0.40.3<br>
|
||||
-----------------------------------------------<br>
|
||||
* Bladeburner Changes:<br>
|
||||
*** Increased the effect that agi and dexterity have on action time<br>
|
||||
|
@ -475,13 +475,6 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "tprint() call has incorrect number of arguments. Takes 1 argument");
|
||||
}
|
||||
var x = args.toString();
|
||||
if (isHTML(x)) {
|
||||
Player.takeDamage(1);
|
||||
dialogBoxCreate("You suddenly feel a sharp shooting pain through your body as an angry voice in your head exclaims: <br><br>" +
|
||||
"DON'T USE TPRINT() TO OUTPUT HTML ELEMENTS TO YOUR TERMINAL!!!!<br><br>" +
|
||||
"(You lost 1 HP)");
|
||||
return;
|
||||
}
|
||||
post(workerScript.scriptRef.filename + ": " + args.toString());
|
||||
},
|
||||
clearLog : function() {
|
||||
@ -1839,21 +1832,35 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Could not find port: " + port + ". This is a bug contact the game developer");
|
||||
}
|
||||
return port.write(data);
|
||||
} else if (isString(port)) { //Write to text file
|
||||
} else if (isString(port)) { //Write to script or text file
|
||||
var fn = port;
|
||||
var server = getServer(workerScript.serverIp);
|
||||
var server = workerScript.getServer();
|
||||
if (server == null) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in write(). This is a bug please contact game dev");
|
||||
}
|
||||
var txtFile = getTextFile(fn, server);
|
||||
if (txtFile == null) {
|
||||
txtFile = createTextFile(fn, data, server);
|
||||
return true;
|
||||
}
|
||||
if (mode === "w") {
|
||||
txtFile.write(data);
|
||||
if (isScriptFilename(fn)) {
|
||||
//Write to script
|
||||
let script = workerScript.getScriptOnServer(fn);
|
||||
if (script == null) {
|
||||
//Create a new script
|
||||
script = new Script(fn, data, server.ip);
|
||||
server.scripts.push(script);
|
||||
return true;
|
||||
}
|
||||
mode === "w" ? script.code = data : script.code += data;
|
||||
script.updateRamUsage();
|
||||
} else {
|
||||
txtFile.append(data);
|
||||
//Write to text file
|
||||
let txtFile = getTextFile(fn, server);
|
||||
if (txtFile == null) {
|
||||
txtFile = createTextFile(fn, data, server);
|
||||
return true;
|
||||
}
|
||||
if (mode === "w") {
|
||||
txtFile.write(data);
|
||||
} else {
|
||||
txtFile.append(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
@ -1895,17 +1902,27 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "ERROR: Could not find port: " + port + ". This is a bug contact the game developer");
|
||||
}
|
||||
return port.read();
|
||||
} else if (isString(port)) { //Read from text file
|
||||
var fn = port;
|
||||
var server = getServer(workerScript.serverIp);
|
||||
} else if (isString(port)) { //Read from script or text file
|
||||
let fn = port;
|
||||
let server = getServer(workerScript.serverIp);
|
||||
if (server == null) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in read(). This is a bug please contact game dev");
|
||||
}
|
||||
var txtFile = getTextFile(fn, server);
|
||||
if (txtFile !== null) {
|
||||
return txtFile.text;
|
||||
if (isScriptFilename(fn)) {
|
||||
//Read from script
|
||||
let script = workerScript.getScriptOnServer(fn);
|
||||
if (script == null) {
|
||||
return "";
|
||||
}
|
||||
return script.code;
|
||||
} else {
|
||||
return "";
|
||||
//Read from text file
|
||||
let txtFile = getTextFile(fn, server);
|
||||
if (txtFile !== null) {
|
||||
return txtFile.text;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for read(): " + port);
|
||||
|
@ -57,7 +57,7 @@ WorkerScript.prototype.getServer = function() {
|
||||
//Returns the Script object for the underlying script
|
||||
WorkerScript.prototype.getScript = function() {
|
||||
let server = this.getServer();
|
||||
for (var i = 0; i < server.scripts.length; ++i) {
|
||||
for (let i = 0; i < server.scripts.length; ++i) {
|
||||
if (server.scripts[i].filename === this.name) {
|
||||
return server.scripts[i];
|
||||
}
|
||||
@ -66,6 +66,19 @@ WorkerScript.prototype.getScript = function() {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Returns the Script object for the specified script
|
||||
WorkerScript.prototype.getScriptOnServer = function(fn, server) {
|
||||
if (server == null) {
|
||||
server = this.getServer();
|
||||
}
|
||||
for (let i = 0; i < server.scripts.length; ++i) {
|
||||
if (server.scripts[i].filename === fn) {
|
||||
return server.scripts[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
WorkerScript.prototype.shouldLog = function(fn) {
|
||||
return (this.disableLogs.ALL == null && this.disableLogs[fn] == null);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import {Augmentations, applyAugmentation,
|
||||
AugmentationNames,
|
||||
PlayerOwnedAugmentation} from "./Augmentations";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CodingContractRewardType} from "./CodingContracts";
|
||||
import {Company, Companies, getNextCompanyPosition,
|
||||
getJobRequirementText, CompanyPosition,
|
||||
CompanyPositions} from "./Company";
|
||||
@ -2278,6 +2279,52 @@ PlayerObject.prototype.queueAugmentation = function(name) {
|
||||
this.queuedAugmentations.push(new PlayerOwnedAugmentation(name));
|
||||
}
|
||||
|
||||
/************* Coding Contracts **************/
|
||||
PlayerObject.prototype.gainCodingContractReward = function(reward, difficulty=1) {
|
||||
if (reward == null || reward.type == null || reward == null) {
|
||||
return `No reward for this contract`;
|
||||
}
|
||||
|
||||
/* eslint-disable no-case-declarations */
|
||||
switch (reward.type) {
|
||||
case CodingContractRewardType.FactionReputation:
|
||||
if (reward.name == null || !(Factions[reward.name] instanceof Faction)) {
|
||||
// If no/invalid faction was designated, just give rewards to all factions
|
||||
reward.type = CodingContractRewardType.FactionReputationAll;
|
||||
return this.gainCodingContractReward(reward);
|
||||
}
|
||||
var repGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||
Factions[reward.name].playerReputation += repGain;
|
||||
return `Gained ${repGain} faction reputation for ${reward.name}`;
|
||||
case CodingContractRewardType.FactionReputationAll:
|
||||
const totalGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||
const gainPerFaction = Math.floor(totalGain / this.factions.length);
|
||||
for (const facName of this.factions) {
|
||||
if (!(Factions[facName] instanceof Faction)) { continue; }
|
||||
Factions[facName].playerReputation += gainPerFaction;
|
||||
}
|
||||
return `Gained ${gainPerFaction} reputation for each faction you are a member of`;
|
||||
break;
|
||||
case CodingContractRewardType.CompanyReputation:
|
||||
if (reward.name == null || !(Companies[reward.name] instanceof Company)) {
|
||||
//If no/invalid company was designated, just give rewards to all factions
|
||||
reward.type = CodingContractRewardType.FactionReputationAll;
|
||||
return this.gainCodingContractReward(reward);
|
||||
}
|
||||
var repGain = CONSTANTS.CodingContractBaseCompanyRepGain * difficulty;
|
||||
Companies[reward.name].playerReputation += repGain;
|
||||
return `Gained ${repGain} company reputation for ${reward.name}`;
|
||||
break;
|
||||
case CodingContractRewardType.Money:
|
||||
default:
|
||||
var moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty;
|
||||
this.gainMoney(moneyGain);
|
||||
return `Gained ${numeralWrapper.format(moneyGain, '$0.000a')}`;
|
||||
break;
|
||||
}
|
||||
/* eslint-enable no-case-declarations */
|
||||
}
|
||||
|
||||
/* Functions for saving and loading the Player data */
|
||||
function loadPlayer(saveString) {
|
||||
Player = JSON.parse(saveString, Reviver);
|
||||
|
@ -371,12 +371,13 @@ function checkValidFilename(filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function Script() {
|
||||
this.filename = "";
|
||||
this.code = "";
|
||||
function Script(fn = "", code = "", server = "") {
|
||||
this.filename = fn;
|
||||
this.code = code;
|
||||
this.ramUsage = 0;
|
||||
this.server = ""; //IP of server this script is on
|
||||
this.server = server; //IP of server this script is on
|
||||
this.module = "";
|
||||
if (this.code !== "") {this.updateRamUsage();}
|
||||
};
|
||||
|
||||
//Get the script data from the Script Editor and save it to the object
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CodingContract, ContractTypes} from "./CodingContracts";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {Player} from "./Player";
|
||||
@ -37,11 +38,12 @@ function Server(params={ip:createRandomIp(), hostname:""}) {
|
||||
this.ramUsed = 0;
|
||||
this.cpuCores = 1; //Max of 8, affects hacking times and Hacking Mission starting Cores
|
||||
|
||||
this.scripts = [];
|
||||
this.runningScripts = []; //Stores RunningScript objects
|
||||
this.programs = [];
|
||||
this.messages = [];
|
||||
this.textFiles = [];
|
||||
this.scripts = [];
|
||||
this.runningScripts = []; //Stores RunningScript objects
|
||||
this.programs = [];
|
||||
this.messages = [];
|
||||
this.textFiles = [];
|
||||
this.contracts = [];
|
||||
this.dir = 0; //new Directory(this, null, ""); TODO
|
||||
|
||||
/* Hacking information (only valid for "foreign" aka non-purchased servers) */
|
||||
@ -113,6 +115,32 @@ Server.prototype.weaken = function(amt) {
|
||||
this.capDifficulty();
|
||||
}
|
||||
|
||||
// Coding Contracts
|
||||
Server.prototype.addContract = function(contract) {
|
||||
this.contracts.push(contract);
|
||||
}
|
||||
|
||||
Server.prototype.removeContract = function(contract) {
|
||||
if (contract instanceof CodingContract) {
|
||||
this.contracts = this.contracts.filter((c) => {
|
||||
return c.fn !== contract.fn;
|
||||
});
|
||||
} else {
|
||||
this.contracts = this.contracts.filter((c) => {
|
||||
return c.fn !== contract;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Server.prototype.getContract = function(contractName) {
|
||||
for (const contract of this.contracts) {
|
||||
if (contract.fn === contractName) {
|
||||
return contract;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//Functions for loading and saving a Server
|
||||
Server.prototype.toJSON = function() {
|
||||
return Generic_toJSON("Server", this);
|
||||
|
@ -1,9 +1,11 @@
|
||||
import {substituteAliases, printAliases,
|
||||
parseAliasDeclaration,
|
||||
removeAlias, GlobalAliases,
|
||||
Aliases} from "./Alias";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Programs} from "./CreateProgram";
|
||||
Aliases} from "./Alias";
|
||||
import {CodingContract, CodingContractResult,
|
||||
CodingContractRewardType} from "./CodingContracts";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {executeDarkwebTerminalCommand,
|
||||
checkIfConnectedToDarkweb,
|
||||
DarkWebItems} from "./DarkWeb";
|
||||
@ -62,7 +64,7 @@ $(document).keydown(function(event) {
|
||||
//Terminal
|
||||
if (routing.isOn(Page.Terminal)) {
|
||||
var terminalInput = document.getElementById("terminal-input-text-box");
|
||||
if (terminalInput != null && !event.ctrlKey && !event.shiftKey) {terminalInput.focus();}
|
||||
if (terminalInput != null && !event.ctrlKey && !event.shiftKey && !Terminal.contractOpen) {terminalInput.focus();}
|
||||
|
||||
if (event.keyCode === KEY.ENTER) {
|
||||
event.preventDefault(); //Prevent newline from being entered in Script Editor
|
||||
@ -251,7 +253,7 @@ $(document).keydown(function(e) {
|
||||
terminalCtrlPressed = true;
|
||||
} else if (e.shiftKey) {
|
||||
shiftKeyPressed = true;
|
||||
} else if (terminalCtrlPressed || shiftKeyPressed) {
|
||||
} else if (terminalCtrlPressed || shiftKeyPressed || Terminal.contractOpen) {
|
||||
//Don't focus
|
||||
} else {
|
||||
var inputTextBox = document.getElementById("terminal-input-text-box");
|
||||
@ -523,6 +525,8 @@ let Terminal = {
|
||||
commandHistory: [],
|
||||
commandHistoryIndex: 0,
|
||||
|
||||
contractOpen: false, //True if a Coding Contract prompt is opened
|
||||
|
||||
resetTerminalInput: function() {
|
||||
if (FconfSettings.WRAP_INPUT) {
|
||||
document.getElementById("terminal-input-td").innerHTML =
|
||||
@ -1354,9 +1358,11 @@ let Terminal = {
|
||||
}
|
||||
|
||||
//Check if its a script or just a program/executable
|
||||
//if (isScriptFilename(executableName)) {
|
||||
//Dont use isScriptFilename here because `executableName` includes the args too
|
||||
if (executableName.includes(".script") || executableName.includes(".js") || executableName.includes(".ns")) {
|
||||
Terminal.runScript(executableName);
|
||||
} else if (executableName.endsWith(".cct")) {
|
||||
Terminal.runContract(executableName);
|
||||
} else {
|
||||
Terminal.runProgram(executableName);
|
||||
}
|
||||
@ -1744,6 +1750,15 @@ let Terminal = {
|
||||
allFiles.push(s.textFiles[i].fn);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < s.contracts.length; ++i) {
|
||||
if (filter) {
|
||||
if (s.contracts[i].fn.includes(filter)) {
|
||||
allFiles.push(s.contracts[i].fn);
|
||||
}
|
||||
} else {
|
||||
allFiles.push(s.contracts[i].fn);
|
||||
}
|
||||
}
|
||||
|
||||
//Sort the files alphabetically then print each
|
||||
allFiles.sort();
|
||||
@ -1969,9 +1984,9 @@ let Terminal = {
|
||||
post("Server base security level: " + targetServer.baseDifficulty);
|
||||
post("Server current security level: " + targetServer.hackDifficulty);
|
||||
post("Server growth rate: " + targetServer.serverGrowth);
|
||||
post("Netscript hack() execution time: " + numeralWrapper.format(scriptCalculateHackingTime(targetServer), '0.0') + "s");
|
||||
post("Netscript grow() execution time: " + numeralWrapper.format(scriptCalculateGrowTime(targetServer), '0.0') + "s");
|
||||
post("Netscript weaken() execution time: " + numeralWrapper.format(scriptCalculateWeakenTime(targetServer), '0.0') + "s");
|
||||
post("Netscript hack() execution time: " + numeralWrapper.format(calculateHackingTime(targetServer), '0.0') + "s");
|
||||
post("Netscript grow() execution time: " + numeralWrapper.format(calculateGrowTime(targetServer), '0.0') + "s");
|
||||
post("Netscript weaken() execution time: " + numeralWrapper.format(calculateWeakenTime(targetServer), '0.0') + "s");
|
||||
};
|
||||
programHandlers[Programs.AutoLink.name] = () => {
|
||||
post("This executable cannot be run.");
|
||||
@ -2132,7 +2147,42 @@ let Terminal = {
|
||||
|
||||
|
||||
post("ERROR: No such script");
|
||||
}
|
||||
},
|
||||
|
||||
runContract: async function(contractName) {
|
||||
// There's already an opened contract
|
||||
if (Terminal.contractOpen) {
|
||||
return post("ERROR: There's already a Coding Contract in Progress");
|
||||
}
|
||||
Terminal.contractOpen = true;
|
||||
|
||||
const serv = Player.getCurrentServer();
|
||||
const contract = serv.getContract(contractName);
|
||||
if (contract == null) {
|
||||
return post("ERROR: No such contract");
|
||||
}
|
||||
const res = await contract.prompt();
|
||||
|
||||
switch (res) {
|
||||
case CodingContractResult.Success:
|
||||
var reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty());
|
||||
post(`Contract SUCCESS - ${reward}`);
|
||||
serv.removeContract(contract);
|
||||
break;
|
||||
case CodingContractResult.Failure:
|
||||
post("Contract <p style='color:red;display:inline'>FAILED</p> - Contract is now self-destructing");
|
||||
++contract.tries;
|
||||
if (contract.tries >= contract.getMaxNumTries()) {
|
||||
serv.removeContract(contract);
|
||||
}
|
||||
break;
|
||||
case CodingContractResult.Cancelled:
|
||||
default:
|
||||
post("Contract cancelled");
|
||||
break;
|
||||
}
|
||||
Terminal.contractOpen = false;
|
||||
},
|
||||
};
|
||||
|
||||
export {postNetburnerText, Terminal};
|
||||
|
463
src/data/codingcontracttypes.ts
Normal file
463
src/data/codingcontracttypes.ts
Normal file
@ -0,0 +1,463 @@
|
||||
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
||||
|
||||
/* tslint:disable:completed-docs no-magic-numbers arrow-return-shorthand */
|
||||
|
||||
/* Function that generates a valid 'data' for a contract type */
|
||||
export type GeneratorFunc = () => any;
|
||||
|
||||
/* Function that checks if the provided solution is the correct one */
|
||||
export type SolverFunc = (data: any, answer: string) => boolean;
|
||||
|
||||
/* Function that returns a string with the problem's description.
|
||||
Requires the 'data' of a Contract as input */
|
||||
export type DescriptionFunc = (data: any) => string;
|
||||
|
||||
export interface ICodingContractTypeMetadata {
|
||||
desc: DescriptionFunc;
|
||||
difficulty: number;
|
||||
gen: GeneratorFunc;
|
||||
name: string;
|
||||
numTries: number;
|
||||
solver: SolverFunc;
|
||||
}
|
||||
|
||||
export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||
{
|
||||
desc: (n: number) => {
|
||||
return ["A prime factor is a factor that is a prime number.",
|
||||
`What is the largest prime factor of ${n}?`].join(" ");
|
||||
},
|
||||
difficulty: 1,
|
||||
gen: () => {
|
||||
return getRandomInt(500, 9e9);
|
||||
},
|
||||
name: "Find Largest Prime Factor",
|
||||
numTries: 10,
|
||||
solver: (data: number, ans: string) => {
|
||||
let fac: number = 2;
|
||||
let n: number = data;
|
||||
while (n > fac) {
|
||||
if (n % fac === 0) {
|
||||
n = Math.round(n / fac);
|
||||
fac = 2;
|
||||
} else {
|
||||
++fac;
|
||||
}
|
||||
}
|
||||
|
||||
return fac === parseInt(ans, 10);
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (n: number[]) => {
|
||||
return ["Given the following integer array, find the contiguous subarray",
|
||||
"(containing at least one number) which has the largest sum and return that sum.",
|
||||
"'Sum' refers to the sum of all the numbers in the subarray.",
|
||||
`${n.toString()}`].join(" ");
|
||||
},
|
||||
difficulty: 1,
|
||||
gen: () => {
|
||||
const len: number = getRandomInt(5, 40);
|
||||
const arr: number[] = [];
|
||||
arr.length = len;
|
||||
for (let i: number = 0; i < len; ++i) {
|
||||
arr[i] = getRandomInt(-10, 10);
|
||||
}
|
||||
|
||||
return arr;
|
||||
},
|
||||
name: "Subarray with Maximum Sum",
|
||||
numTries: 10,
|
||||
solver: (data: number[], ans: string) => {
|
||||
const nums: number[] = data.slice();
|
||||
for (let i: number = 1; i < nums.length; i++) {
|
||||
nums[i] = Math.max(nums[i], nums[i] + nums[i - 1]);
|
||||
}
|
||||
|
||||
return parseInt(ans, 10) === Math.max(...nums);
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (n: number) => {
|
||||
return ["It is possible write four as a sum in exactly four different ways:\n\n",
|
||||
" 3 + 1\n",
|
||||
" 2 + 2\n",
|
||||
" 2 + 1 + 1\n",
|
||||
" 1 + 1 + 1 + 1\n\n",
|
||||
`How many different ways can ${n} be written as a sum of at least`,
|
||||
"two positive integers?"].join(" ");
|
||||
},
|
||||
difficulty: 1.5,
|
||||
gen: () => {
|
||||
return getRandomInt(8, 100);
|
||||
},
|
||||
name: "Total Ways to Sum",
|
||||
numTries: 10,
|
||||
solver: (data: number, ans: string) => {
|
||||
const ways: number[] = [1];
|
||||
ways.length = data + 1;
|
||||
ways.fill(0, 1);
|
||||
for (let i: number = 1; i < data; ++i) {
|
||||
for (let j: number = i; j <= data; ++j) {
|
||||
ways[j] += ways[j - i];
|
||||
}
|
||||
}
|
||||
|
||||
return ways[data] === parseInt(ans, 10);
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (n: number[][]) => {
|
||||
let d: string = ["Given the following array of array of numbers representing a 2D matrix,",
|
||||
"return the elements of the matrix as an array in spiral order:\n\n"].join(" ");
|
||||
for (const line of n) {
|
||||
d += `${line.toString()},\n`;
|
||||
}
|
||||
d += ["\nHere is an example of what spiral order should be:",
|
||||
"\nExample:",
|
||||
" [\n",
|
||||
" [1, 2, 3],\n",
|
||||
" [4, 5, 6],\n",
|
||||
" [7, 8, 9]\n",
|
||||
" ] should result in [1, 2, 3, 6, 9, 8 ,7, 4, 5]\n\n",
|
||||
"Note that the matrix will not always be square:\n",
|
||||
" [\n",
|
||||
" [1, 2, 3, 4]\n",
|
||||
" [5, 6, 7, 8]\n",
|
||||
" [9, 10, 11, 12]\n",
|
||||
" ] should result in [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7"].join(" ");
|
||||
|
||||
return d;
|
||||
},
|
||||
difficulty: 2,
|
||||
gen: () => {
|
||||
const m: number = getRandomInt(1, 10);
|
||||
const n: number = getRandomInt(1, 10);
|
||||
const matrix: number[][] = [];
|
||||
matrix.length = m;
|
||||
for (let i: number = 0; i < m; ++i) {
|
||||
matrix[i].length = n;
|
||||
}
|
||||
|
||||
for (let i: number = 0; i < m; ++i) {
|
||||
for (let j: number = 0; j < n; ++j) {
|
||||
matrix[i][j] = getRandomInt(1, 50);
|
||||
}
|
||||
}
|
||||
|
||||
return matrix;
|
||||
},
|
||||
name: "Spiralize Matrix",
|
||||
numTries: 10,
|
||||
solver: (data: number[][], ans: string) => {
|
||||
const spiral: number[] = [];
|
||||
const m: number = data.length;
|
||||
const n: number = data[0].length;
|
||||
let u: number = 0;
|
||||
let d: number = m - 1;
|
||||
let l: number = 0;
|
||||
let r: number = n - 1;
|
||||
let k: number = 0;
|
||||
while (true) {
|
||||
// Up
|
||||
for (let col: number = l; col <= r; col++) {
|
||||
spiral[k] = data[u][col];
|
||||
++k;
|
||||
}
|
||||
if (++u > d) { break; }
|
||||
|
||||
// Right
|
||||
for (let row: number = u; row <= d; row++) {
|
||||
spiral[k] = data[row][r];
|
||||
++k;
|
||||
}
|
||||
if (--r < l) { break; }
|
||||
|
||||
// Down
|
||||
for (let col: number = r; col >= l; col--) {
|
||||
spiral[k] = data[d][col];
|
||||
++k;
|
||||
}
|
||||
if (--d < u) { break; }
|
||||
|
||||
// Left
|
||||
for (let row: number = d; row >= u; row--) {
|
||||
spiral[k] = data[row][l];
|
||||
++k;
|
||||
}
|
||||
if (++l > r) { break; }
|
||||
}
|
||||
const playerAns: any[] = ans.split(",");
|
||||
for (let i: number = 0; i < playerAns.length; ++i) {
|
||||
playerAns[i] = parseInt(playerAns[i], 10);
|
||||
}
|
||||
if (spiral.length !== playerAns.length) { return false; }
|
||||
for (let i: number = 0; i < spiral.length; ++i) {
|
||||
if (spiral[i] !== playerAns[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (arr: number[]) => {
|
||||
return ["You are given the following array of integers:\n\n",
|
||||
`${arr}\n\n`,
|
||||
"Each element in the array represents your maximum jump length",
|
||||
"at that position. Assuming you are initially positioned",
|
||||
"at the start of the array, determine whether you are",
|
||||
"able to reach the last index exactly.\n\n",
|
||||
"Your answer should be submitted as 1 or 0, representing true and false respectively"].join(" ");
|
||||
},
|
||||
difficulty: 2.5,
|
||||
gen: () => {
|
||||
const len: number = getRandomInt(1, 25);
|
||||
const arr: number[] = [];
|
||||
arr.length = len;
|
||||
for (let i: number = 0; i < arr.length; ++i) {
|
||||
arr[i] = getRandomInt(0, 24);
|
||||
}
|
||||
},
|
||||
name: "Array Jumping Game",
|
||||
numTries: 1,
|
||||
solver: (data: number[], ans: string) => {
|
||||
const n: number = data.length;
|
||||
let i: number = 0;
|
||||
for (let reach: number = 0; i < n && i <= reach; ++i) {
|
||||
reach = Math.max(i + data[i], reach);
|
||||
}
|
||||
const solution: boolean = (i === n);
|
||||
|
||||
if (ans === "1" && solution) { return true; }
|
||||
if (ans === "0" && !solution) { return true; }
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (arr: number[][]) => {
|
||||
return ["Given the following array of array of numbers representing a list of",
|
||||
"intervals, merge all overlapping intervals.\n\n",
|
||||
`${arr}\n\n`,
|
||||
"Example:\n\n",
|
||||
"[[1, 3], [8, 10], [2, 6], [10, 16]]\n\n",
|
||||
"would merge into [[1, 6], [8, 16]].\n\n",
|
||||
"The intervals must be returned in ASCENDING order.",
|
||||
"You can assume that in an interval, the first number will always be",
|
||||
"smaller than the second."].join(" ");
|
||||
},
|
||||
difficulty: 3,
|
||||
gen: () => {
|
||||
const intervals: number[][] = [];
|
||||
const numIntervals: number = getRandomInt(1, 15);
|
||||
for (let i: number = 0; i < numIntervals; ++i) {
|
||||
const start: number = getRandomInt(1, 25);
|
||||
const end: number = start + getRandomInt(1, 10);
|
||||
intervals.push([start, end]);
|
||||
}
|
||||
|
||||
return intervals;
|
||||
},
|
||||
name: "Merge Overlapping Intervals",
|
||||
numTries: 15,
|
||||
solver: (data: number[][], ans: string) => {
|
||||
const intervals: number[][] = data.slice();
|
||||
intervals.sort((a: number[], b: number[]) => {
|
||||
return a[0] - b[0];
|
||||
});
|
||||
|
||||
const result: number[][] = [];
|
||||
let start: number = intervals[0][0];
|
||||
let end: number = intervals[0][1];
|
||||
for (const interval of intervals) {
|
||||
if (interval[0] <= end) {
|
||||
end = Math.max(end, interval[1]);
|
||||
} else {
|
||||
result.push([start, end]);
|
||||
start = interval[0];
|
||||
end = interval[1];
|
||||
}
|
||||
}
|
||||
result.push([start, end]);
|
||||
|
||||
const sanitizedResult: string = result
|
||||
.toString()
|
||||
.replace(/\s/g, "");
|
||||
const sanitizedAns: string = ans.replace(/\s/g, "");
|
||||
|
||||
return sanitizedResult === sanitizedAns;
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: string) => {
|
||||
return ["Given the following string containing only digits, determine",
|
||||
"an array with all possible valid IP address combinations",
|
||||
"that can be created from the string:\n\n",
|
||||
`${data}\n\n`,
|
||||
"Example:\n\n",
|
||||
"'25525511135' -> ['255.255.11.135', '255.255.111.35']"].join(" ");
|
||||
},
|
||||
difficulty: 3,
|
||||
gen: () => {
|
||||
let str: string = "";
|
||||
for (let i: number = 0; i < 4; ++i) {
|
||||
const num: number = getRandomInt(0, 255);
|
||||
const convNum: string = num.toString();
|
||||
str += convNum;
|
||||
}
|
||||
|
||||
return str;
|
||||
},
|
||||
name: "Generate IP Addresses",
|
||||
numTries: 10,
|
||||
solver: (data: string, ans: string) => {
|
||||
const ret: string[] = [];
|
||||
for (let a: number = 1; a <= 3; ++a) {
|
||||
for (let b: number = 1; b <= 3; ++b) {
|
||||
for (let c: number = 1; c <= 3; ++c) {
|
||||
for (let d: number = 1; d <= 3; ++d) {
|
||||
if (a + b + c + d === data.length) {
|
||||
const A: number = parseInt(data.substring(0, a), 10);
|
||||
const B: number = parseInt(data.substring(a, a + b), 10);
|
||||
const C: number = parseInt(data.substring(a + b, a + b + c), 10);
|
||||
const D: number = parseInt(data.substring(a + b + c, a + b + c + d), 10);
|
||||
if (A <= 255 && B <= 255 && C <= 255 && D <= 255) {
|
||||
const ip: string = [A.toString(), ".",
|
||||
B.toString(), ".",
|
||||
C.toString(), ".",
|
||||
D.toString()].join("");
|
||||
if (ip.length === data.length + 3) {
|
||||
ret.push(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let sanitizedAns: string = ans.replace(/\s/g, "");
|
||||
if (sanitizedAns.length === 0 || sanitizedAns[0] !== "[" || sanitizedAns[sanitizedAns.length - 1] !== "]") {
|
||||
return false;
|
||||
}
|
||||
sanitizedAns = sanitizedAns.slice(1, -1); // Remove []
|
||||
const ansArr: string[] = sanitizedAns.split(",");
|
||||
if (ansArr.length !== ret.length) { return false; }
|
||||
for (const ipInAns of ansArr) {
|
||||
if (!ret.includes(ipInAns)) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: number[]) => {
|
||||
return ["You are given the following array of stock prices where the i-th element",
|
||||
"represents the stock price on day i:\n\n",
|
||||
`${data}\n\n`,
|
||||
"Determine the maximum possible profit you can earn using at most",
|
||||
"one transaction (i.e. you can only buy and sell the stock once). If no profit can be made",
|
||||
"then the answer should be 0. Note",
|
||||
"that you have to buy the stock before you can sell it"].join(" ");
|
||||
},
|
||||
difficulty: 1,
|
||||
gen: () => {
|
||||
const len: number = getRandomInt(1, 50);
|
||||
const arr: number[] = [];
|
||||
arr.length = len;
|
||||
for (let i: number = 0; i < len; ++i) {
|
||||
arr[i] = getRandomInt(1, 200);
|
||||
}
|
||||
|
||||
return arr;
|
||||
},
|
||||
name: "Algorithmic Stock Trader I",
|
||||
numTries: 5,
|
||||
solver: (data: number[], ans: string) => {
|
||||
let maxCur: number = 0;
|
||||
let maxSoFar: number = 0;
|
||||
for (let i: number = 1; i < data.length; ++i) {
|
||||
maxCur = Math.max(0, maxCur += data[i] - data[i - 1]);
|
||||
maxSoFar = Math.max(maxCur, maxSoFar);
|
||||
}
|
||||
|
||||
return maxSoFar.toString() === ans;
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: number[]) => {
|
||||
return ["You are given the following array of stock prices where the i-th element",
|
||||
"represents the stock price on day i:\n\n",
|
||||
`${data}\n\n`,
|
||||
"Determine the maximum possible profit you can earn using as many",
|
||||
"transactions as you'd like. A transaction is defined as buying",
|
||||
"and then selling one share of the stock. Note that you cannot",
|
||||
"engage in multiple transactions at once. In other words, you",
|
||||
"must sell the stock before you buy it again.\n\n",
|
||||
"If no profit can be made, then the answer should be 0"].join(" ");
|
||||
},
|
||||
difficulty: 2,
|
||||
gen: () => {
|
||||
const len: number = getRandomInt(1, 50);
|
||||
const arr: number[] = [];
|
||||
arr.length = len;
|
||||
for (let i: number = 0; i < len; ++i) {
|
||||
arr[i] = getRandomInt(1, 200);
|
||||
}
|
||||
|
||||
return arr;
|
||||
},
|
||||
name: "Algorithmic Stock Trader II",
|
||||
numTries: 10,
|
||||
solver: (data: number[], ans: string) => {
|
||||
let profit: number = 0;
|
||||
for (let p: number = 1; p < data.length; ++p) {
|
||||
profit += Math.max(data[p] - data[p - 1], 0);
|
||||
}
|
||||
|
||||
return profit.toString() === ans;
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: (data: number[]) => {
|
||||
return ["You are given the following array of stock prices where the i-th element",
|
||||
"represents the stock price on day i:\n\n",
|
||||
`${data}\n\n`,
|
||||
"Determine the maximum possible profit you can earn using at most ",
|
||||
"two transactions. A transaction is defined as buying",
|
||||
"and then selling one share of the stock. Note that you cannot",
|
||||
"engage in multiple transactions at once. In other words, you",
|
||||
"must sell the stock before you buy it again.\n\n",
|
||||
"If no profit can be made, then the answer should be 0"].join(" ");
|
||||
},
|
||||
difficulty: 5,
|
||||
gen: () => {
|
||||
const len: number = getRandomInt(1, 50);
|
||||
const arr: number[] = [];
|
||||
arr.length = len;
|
||||
for (let i: number = 0; i < len; ++i) {
|
||||
arr[i] = getRandomInt(1, 200);
|
||||
}
|
||||
|
||||
return arr;
|
||||
},
|
||||
name: "Algorithmic Stock Trader III",
|
||||
numTries: 10,
|
||||
solver: (data: number[], ans: string) => {
|
||||
let hold1: number = Number.MIN_SAFE_INTEGER;
|
||||
let hold2: number = Number.MIN_SAFE_INTEGER;
|
||||
let release1: number = 0;
|
||||
let release2: number = 0;
|
||||
for (const price of data) {
|
||||
release2 = Math.max(release2, hold2 + price);
|
||||
hold2 = Math.max(hold2, release1 - price);
|
||||
release1 = Math.max(release1, hold1 + price);
|
||||
hold1 = Math.max(hold1, price * -1);
|
||||
}
|
||||
|
||||
return release2.toString() === ans;
|
||||
},
|
||||
},
|
||||
];
|
@ -150,7 +150,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["beyond-man.lit"],
|
||||
maxRamExponent: {
|
||||
max: 9,
|
||||
min: 5
|
||||
min: 5,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 40e9,
|
||||
@ -226,7 +226,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
],
|
||||
maxRamExponent: {
|
||||
max: 9,
|
||||
min: 7
|
||||
min: 7,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 22e9,
|
||||
@ -297,7 +297,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["simulated-reality.lit"],
|
||||
maxRamExponent: {
|
||||
max: 11,
|
||||
min: 7
|
||||
min: 7,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 1800e6,
|
||||
@ -404,7 +404,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["beyond-man.lit"],
|
||||
maxRamExponent: {
|
||||
max: 8,
|
||||
min: 5
|
||||
min: 5,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 750e6,
|
||||
@ -431,7 +431,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["A-Green-Tomorrow.lit"],
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 800e6,
|
||||
@ -479,7 +479,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "univ-energy",
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 1200e6,
|
||||
@ -506,7 +506,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["coded-intelligence.lit"],
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 900000000,
|
||||
@ -533,7 +533,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["synthetic-muscles.lit"],
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 700000000,
|
||||
@ -631,7 +631,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["history-of-synthoids.lit"],
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 1000000000,
|
||||
@ -706,7 +706,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
],
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 900000000,
|
||||
@ -755,7 +755,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["A-Green-Tomorrow.lit"],
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 3
|
||||
min: 3,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 1750000000,
|
||||
@ -825,7 +825,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "unitalife",
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 1100000000,
|
||||
@ -851,7 +851,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "lexo-corp",
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 800000000,
|
||||
@ -877,7 +877,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "rho-construction",
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 700000000,
|
||||
@ -904,7 +904,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["sector-12-crime.lit"],
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 750000000,
|
||||
@ -930,7 +930,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "aevum-police",
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 400000000,
|
||||
@ -961,7 +961,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
],
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 250000000,
|
||||
@ -987,7 +987,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "zb-institute",
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 1100000000,
|
||||
@ -1018,7 +1018,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
],
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 350000000,
|
||||
@ -1067,7 +1067,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["tensions-in-tech-race.lit"],
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 550000000,
|
||||
@ -1093,7 +1093,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "the-hub",
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 3
|
||||
min: 3,
|
||||
},
|
||||
moneyAvailable: {
|
||||
max: 200000000,
|
||||
@ -1143,7 +1143,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["simulated-reality.lit"],
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: 275000000,
|
||||
networkLayer: 4,
|
||||
@ -1370,7 +1370,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "millenium-fitness",
|
||||
maxRamExponent: {
|
||||
max: 8,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: 250000000,
|
||||
networkLayer: 6,
|
||||
@ -1393,7 +1393,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
hostname: "powerhouse-fitness",
|
||||
maxRamExponent: {
|
||||
max: 6,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: 900000000,
|
||||
networkLayer: 14,
|
||||
@ -1436,7 +1436,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
],
|
||||
maxRamExponent: {
|
||||
max: 9,
|
||||
min: 5
|
||||
min: 5,
|
||||
},
|
||||
moneyAvailable: 0,
|
||||
networkLayer: 11,
|
||||
@ -1455,7 +1455,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["democracy-is-dead.lit"],
|
||||
maxRamExponent: {
|
||||
max: 8,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: 0,
|
||||
networkLayer: 5,
|
||||
@ -1474,7 +1474,7 @@ export const serverMetadata: IServerMetadata[] = [
|
||||
literature: ["democracy-is-dead.lit"],
|
||||
maxRamExponent: {
|
||||
max: 7,
|
||||
min: 4
|
||||
min: 4,
|
||||
},
|
||||
moneyAvailable: 0,
|
||||
networkLayer: 4,
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib" : ["es2016", "dom"],
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"sourceMap": true,
|
||||
|
@ -17,7 +17,7 @@ function infiltrationBoxClose() {
|
||||
|
||||
function infiltrationBoxOpen() {
|
||||
var box = document.getElementById("infiltration-box-container");
|
||||
box.style.display = "block";
|
||||
box.style.display = "flex";
|
||||
}
|
||||
|
||||
function infiltrationSetText(txt) {
|
||||
|
Loading…
Reference in New Issue
Block a user