diff --git a/doc/source/netscriptcodingcontractapi.rst b/doc/source/netscriptcodingcontractapi.rst index b5dd0714f..44db5e6f2 100644 --- a/doc/source/netscriptcodingcontractapi.rst +++ b/doc/source/netscriptcodingcontractapi.rst @@ -31,6 +31,20 @@ attempt :returns: Boolean indicating whether the solution was correct +getContractType +--------------- + +.. js:function:: getContractType(fn[, hostname/ip=current ip]) + + :param string fn: Filename of the contract + :param string hostname/ip: Hostname or IP of the server containing the contract. + Optional. Defaults to current server if not provided + + Returns a name describing the type of problem posed by the Coding Contract. + (e.g. Find Largest Prime Factor, Total Ways to Sum, etc.) + + :returns: A string with the contract's problem type + getDescription -------------- diff --git a/netscript.js b/netscript.js index d41521685..250f819b7 100644 --- a/netscript.js +++ b/netscript.js @@ -112,7 +112,8 @@ let NetscriptFunctions = "getCityChaos|switchCity|getStamina|joinBladeburnerFaction|getBonusTime|" + // Coding Contract API - "codingcontract|attempt|getData|getDescription|getNumTriesRemaining"; + "codingcontract|attempt|getContractType|getData|getDescription|" + + "getNumTriesRemaining"; var NetscriptHighlightRules = function(options) { var keywordMapper = this.createKeywordMapper({ diff --git a/src/CodingContracts.ts b/src/CodingContracts.ts index aab893d8e..592280172 100644 --- a/src/CodingContracts.ts +++ b/src/CodingContracts.ts @@ -154,6 +154,10 @@ export class CodingContract { return CodingContractTypes[this.type].numTries; } + getType(): string { + return CodingContractTypes[this.type].name; + } + isSolution(solution: string): boolean { return CodingContractTypes[this.type].solver(this.data, solution); } diff --git a/src/Constants.js b/src/Constants.js index 8b7a1ef63..62d33d155 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -506,18 +506,11 @@ let CONSTANTS = { LatestUpdate: ` - v0.40.4 - * Added new Coding Contracts mechanic. Solve programming problems to earn rewards - * The write() and read() Netscript functions now work on scripts - * Added getStockSymbols() Netscript function to the TIX API (by InfraK) - * Added wget() Netscript function - * Added bladeburner.getActionRepGain() function to the Netscript Bladeburner API - * The getLevelUpgradeCost(), getRamUpgradeCost(), and getCoreUpgradeCost() functions in the Hacknet API now return Infinity if the node is at max level. See documentation - * It is now possible to use freely use angled bracket (<, >) and create DOM elements using tprint() - * The game's theme colors can now be set through the Terminal configuration (.fconf). - * You can now switch to the old left-hand main menu bar through the Terminal configuration (.fconf) - * Bug Fix: grow() percentage is no longer reported as Infinity when a server's money is grown from 0 to X - * Bug Fix: Infiltration popup now displays the correct amount of exp gained + v0.40.5 + * Added codingcontract.getContractType() Netscript function + * Bug Fix: codingcontract.getData() Netscript function now returns arrays by value rather than reference + * Bug Fix: Decreased highest possible data value for 'Find Largest Prime Factor' Coding Contract (to avoid hangs when solving it) + * Bug Fix: Fixed a bug that caused game to freeze during Coding Contract generation ` } diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index eeee0d466..c95fe9740 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -4085,17 +4085,35 @@ function NetscriptFunctions(workerScript) { return false; } }, + getContractType : function(fn, ip=workerScript.serverIp) { + if (workerScript.checkingRam) { + return updateStaticRam("getContractType", CONSTANTS.ScriptCodingContractBaseRamCost / 2); + } + updateDynamicRam("getContractType", CONSTANTS.ScriptCodingContractBaseRamCost / 2); + let contract = getCodingContract(fn, ip); + if (contract == null) { + workerScript.log(`ERROR: codingcontract.getData() failed because it could find the specified contract ${fn} on server ${ip}`); + return null; + } + return contract.getType(); + }, getData : function(fn, ip=workerScript.serverIp) { if (workerScript.checkingRam) { return updateStaticRam("getData", CONSTANTS.ScriptCodingContractBaseRamCost / 2); } updateDynamicRam("getData", CONSTANTS.ScriptCodingContractBaseRamCost / 2); - var contract = getCodingContract(fn, ip); + let contract = getCodingContract(fn, ip); if (contract == null) { workerScript.log(`ERROR: codingcontract.getData() failed because it could find the specified contract ${fn} on server ${ip}`); return null; } - return contract.getData(); + let data = contract.getData(); + if (typeof data === "object") { + // Pass a copy + return data.slice(); + } else { + return data; + } }, getDescription : function(fn, ip=workerScript.serverIp) { if (workerScript.checkingRam) { diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index b39761ff4..15bc3a380 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -50,7 +50,7 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ }, difficulty: 1, gen: () => { - return getRandomInt(500, 9e9); + return getRandomInt(500, 1e9); }, name: "Find Largest Prime Factor", numTries: 10, diff --git a/src/engine.js b/src/engine.js index be88bccc4..1f7c59495 100644 --- a/src/engine.js +++ b/src/engine.js @@ -1169,10 +1169,18 @@ const Engine = { reward.type = getRandomInt(0, CodingContractRewardType.Money); // Change type based on certain conditions - if (reward.type === CodingContractRewardType.FactionReputation && Player.factions.length === 0) { + var factionsThatAllowHacking = Player.factions.filter((fac) => { + try { + return Factions[fac].getInfo().offerHackingWork; + } catch (e) { + console.error(`Error when trying to filter Hacking Factions for Coding Contract Generation: ${e}`); + return false; + } + }); + if (reward.type === CodingContractRewardType.FactionReputation && factionsThatAllowHacking.length === 0) { reward.type = CodingContractRewardType.CompanyReputation; } - if (reward.type === CodingContractRewardType.FactionReputationAll && Player.factions.length === 0) { + if (reward.type === CodingContractRewardType.FactionReputationAll && factionsThatAllowHacking.length === 0) { reward.type = CodingContractRewardType.CompanyReputation; } if (reward.type === CodingContractRewardType.CompanyReputation && Player.companyName === "") { @@ -1183,18 +1191,9 @@ const Engine = { switch (reward.type) { case CodingContractRewardType.FactionReputation: // Get a random faction that player is a part of. That - //faction must allow hacking contracts - var numFactions = Player.factions.length; - var randFaction = Player.factions[getRandomInt(0, numFactions - 1)]; - try { - while(Factions[randFaction].getInfo().offerHackingWork !== true) { - randFaction = Player.factions[getRandomInt(0, numFactions - 1)]; - } - reward.name = randFaction; - } catch (e) { - exceptionAlert("Failed to find a faction for Coding Contract Generation: " + e); - } - + // faction must allow hacking contracts + var numFactions = factionsThatAllowHacking.length; + var randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)]; break; case CodingContractRewardType.CompanyReputation: if (Player.companyName !== "") {