diff --git a/doc/source/basicgameplay/codingcontracts.rst b/doc/source/basicgameplay/codingcontracts.rst index e8fdabbd9..d2fadbab7 100644 --- a/doc/source/basicgameplay/codingcontracts.rst +++ b/doc/source/basicgameplay/codingcontracts.rst @@ -370,3 +370,35 @@ The list contains the name of (i.e. the value returned by | | | aaaaaaaaaaaaa -> 1a91031 | | | | aaaaaaaaaaaaaa -> 1a91041 | +-----------------------------------------+------------------------------------------------------------------------------------------+ +| Encryption I: Caesar Cipher | | Caesar cipher is one of the simplest encryption technique. It is a type of | +| | | substitution cipher in which each letter in the plaintext is replaced by a letter some | +| | | fixed number of positions down the alphabet. For example, with a left shift of 3, D | +| | | would be replaced by A, E would become B, and A would become X (because of rotation). | +| | | You are given an array with two elements.The first element is the plaintext, the | +| | | second element is the left shift value. Return the ciphertext as uppercase string. | +| | | Spaces remains the same. | ++-----------------------------------------+------------------------------------------------------------------------------------------+ +| Encryption II: Vigenère Cipher | | Vigenère cipher is a type of polyalphabetic substitution. It uses the Vigenère square | +| | | to encrypt and decrypt plaintext with a keyword. | +| | | Vignenère square: | +| | | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | +| | | +---------------------------------------------------- | +| | | A | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | +| | | B | B C D E F G H I J K L M N O P Q R S T U V W X Y Z A | +| | | C | C D E F G H I J K L M N O P Q R S T U V W X Y Z A B | +| | | D | D E F G H I J K L M N O P Q R S T U V W X Y Z A B C | +| | | E | E F G H I J K L M N O P Q R S T U V W X Y Z A B C D | +| | | ... | +| | | Y | Y Z A B C D E F G H I J K L M N O P Q R S T U V W X | +| | | Z | Z A B C D E F G H I J K L M N O P Q R S T U V W X Y | +| | | For encryption each letter of the plaintext is paired with the corresponding letter of | +| | | a repeating keyword. For example, the plaintext DASHBOARD is encrypted with the | +| | | keyword LINUX: | +| | | Plaintext: DASHBOARD | +| | | Keyword: LINUXLINU | +| | | So, the first letter D is paired with the first letter of the key L. Therefore, row D | +| | | and column L of the Vigenère square are used to get the first cipher letter O. This | +| | | must be repeated for the whole ciphertext. | +| | | You are given an array with two elements. The first element is the plaintext, the | +| | | second element is the keyword. Return the ciphertext as uppercase string. | ++-----------------------------------------+------------------------------------------------------------------------------------------+ diff --git a/package-lock.json b/package-lock.json index 20f43eee6..7fa0ecbb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19131,9 +19131,9 @@ } }, "node_modules/terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, "dependencies": { "commander": "^2.20.0", @@ -37110,9 +37110,9 @@ } }, "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, "requires": { "commander": "^2.20.0", diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index 7c318cd59..f13ba2e74 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -39,6 +39,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI { return { shock: 100 - sl.shock, sync: sl.sync, + memory: sl.memory, hacking: sl.hacking, strength: sl.strength, defense: sl.defense, @@ -349,9 +350,13 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI { continue; } const other = player.sleeves[i]; - if (other.currentTask === SleeveTaskType.Bladeburner && other.bbAction === action) { + if ( + other.currentTask === SleeveTaskType.Bladeburner && + other.bbAction === action && + other.bbContract === contract + ) { throw ctx.helper.makeRuntimeErrorMsg( - `Sleeve ${sleeveNumber} cannot take of contracts because Sleeve ${i} is already performing that action.`, + `Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`, ); } } diff --git a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx index 53f04d8ba..5776619ab 100644 --- a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx +++ b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx @@ -44,7 +44,7 @@ interface ITaskDetails { function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] { // Array of all companies that other sleeves are working at - const forbiddenCompanies = []; + const forbiddenCompanies: string[] = []; for (const otherSleeve of player.sleeves) { if (sleeve === otherSleeve) { continue; @@ -54,13 +54,8 @@ function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] { } } const allJobs: string[] = Object.keys(player.jobs); - for (let i = 0; i < allJobs.length; ++i) { - if (!forbiddenCompanies.includes(allJobs[i])) { - allJobs[i]; - } - } - return allJobs; + return allJobs.filter((company) => !forbiddenCompanies.includes(company)); } function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] { diff --git a/src/Prestige.ts b/src/Prestige.ts index a5dac229c..aed8096e7 100755 --- a/src/Prestige.ts +++ b/src/Prestige.ts @@ -15,6 +15,7 @@ import { updateHashManagerCapacity } from "./Hacknet/HacknetHelpers"; import { prestigeWorkerScripts } from "./NetscriptWorker"; import { Player } from "./Player"; import { Router } from "./ui/GameRoot"; +import { recentScripts } from "./Netscript/RecentScripts"; import { resetPidCounter } from "./Netscript/Pid"; import { LiteratureNames } from "./Literature/data/LiteratureNames"; @@ -309,5 +310,7 @@ export function prestigeSourceFile(flume: boolean): void { // Gain int exp if (Player.sourceFileLvl(5) !== 0 && !flume) Player.gainIntelligenceExp(300); + // Clear recent scripts + recentScripts.splice(0, recentScripts.length); resetPidCounter(); } diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 9bf3744b9..cf1623251 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -1023,6 +1023,8 @@ export interface SleeveSkills { shock: number; /** Current sync of the sleeve [0-100] */ sync: number; + /** Current memory of the sleeve [1-100] */ + memory: number; /** Current hacking skill of the sleeve */ hacking: number; /** Current strength of the sleeve */ diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index 26f29854b..e34dca9e4 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -1653,4 +1653,236 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ return comprLZDecode(ans) === plain && ans.length <= comprLZEncode(plain).length; }, }, + { + desc: (data: [string, number]): string => { + return [ + "Caesar cipher is one of the simplest encryption technique.", + "It is a type of substitution cipher in which each letter in the plaintext ", + "is replaced by a letter some fixed number of positions down the alphabet.", + "For example, with a left shift of 3, D would be replaced by A, ", + "E would become B, and A would become X (because of rotation).\n\n", + "You are given an array with two elements:\n", + `  ["${data[0]}", ${data[1]}]\n`, + "The first element is the plaintext, the second element is the left shift value.\n\n", + "Return the ciphertext as uppercase string. Spaces remains the same.", + ].join(" "); + }, + difficulty: 1, + gen: (): [string, number] => { + // return [plaintext, shift value] + const words = [ + "ARRAY", + "CACHE", + "CLOUD", + "DEBUG", + "EMAIL", + "ENTER", + "FLASH", + "FRAME", + "INBOX", + "LINUX", + "LOGIC", + "LOGIN", + "MACRO", + "MEDIA", + "MODEM", + "MOUSE", + "PASTE", + "POPUP", + "PRINT", + "QUEUE", + "SHELL", + "SHIFT", + "TABLE", + "TRASH", + "VIRUS", + ]; + return [ + words + .sort(() => Math.random() - 0.5) + .slice(0, 5) + .join(" "), + Math.floor(Math.random() * 25 + 1), + ]; + }, + name: "Encryption I: Caesar Cipher", + numTries: 10, + solver: (data: [string, number], ans: string): boolean => { + // data = [plaintext, shift value] + // build char array, shifting via map and join to final results + const cipher = [...data[0]] + .map((a) => (a === " " ? a : String.fromCharCode(((a.charCodeAt(0) - 65 - data[1] + 26) % 26) + 65))) + .join(""); + return cipher === ans; + }, + }, + { + desc: (data: [string, string]): string => { + return [ + "Vigenère cipher is a type of polyalphabetic substitution. It uses ", + "the Vigenère square to encrypt and decrypt plaintext with a keyword.\n\n", + "  Vignenère square:\n", + "         A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \n", + "       +----------------------------------------------------\n", + "     A | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \n", + "     B | B C D E F G H I J K L M N O P Q R S T U V W X Y Z A \n", + "     C | C D E F G H I J K L M N O P Q R S T U V W X Y Z A B\n", + "     D | D E F G H I J K L M N O P Q R S T U V W X Y Z A B C\n", + "     E | E F G H I J K L M N O P Q R S T U V W X Y Z A B C D\n", + "                ...\n", + "     Y | Y Z A B C D E F G H I J K L M N O P Q R S T U V W X\n", + "     Z | Z A B C D E F G H I J K L M N O P Q R S T U V W X Y\n\n", + "For encryption each letter of the plaintext is paired with the corresponding letter of a repeating keyword.", + "For example, the plaintext DASHBOARD is encrypted with the keyword LINUX:\n", + "   Plaintext: DASHBOARD\n", + "   Keyword:   LINUXLINU\n", + "So, the first letter D is paired with the first letter of the key L. Therefore, row D and column L of the ", + "Vigenère square are used to get the first cipher letter O. This must be repeated for the whole ciphertext.\n\n", + "You are given an array with two elements:\n", + `  ["${data[0]}", "${data[1]}"]\n`, + "The first element is the plaintext, the second element is the keyword.\n\n", + "Return the ciphertext as uppercase string.", + ].join(" "); + }, + difficulty: 2, + gen: (): [string, string] => { + // return [plaintext, keyword] + const words = [ + "ARRAY", + "CACHE", + "CLOUD", + "DEBUG", + "EMAIL", + "ENTER", + "FLASH", + "FRAME", + "INBOX", + "LINUX", + "LOGIC", + "LOGIN", + "MACRO", + "MEDIA", + "MODEM", + "MOUSE", + "PASTE", + "POPUP", + "PRINT", + "QUEUE", + "SHELL", + "SHIFT", + "TABLE", + "TRASH", + "VIRUS", + ]; + const keys = [ + "ALGORITHM", + "BANDWIDTH", + "BLOGGER", + "BOOKMARK", + "BROADBAND", + "BROWSER", + "CAPTCHA", + "CLIPBOARD", + "COMPUTING", + "COMMAND", + "COMPILE", + "COMPRESS", + "COMPUTER", + "CONFIGURE", + "DASHBOARD", + "DATABASE", + "DESKTOP", + "DIGITAL", + "DOCUMENT", + "DOWNLOAD", + "DYNAMIC", + "EMOTICON", + "ENCRYPT", + "EXABYTE", + "FIREWALL", + "FIRMWARE", + "FLAMING", + "FLOWCHART", + "FREEWARE", + "GIGABYTE", + "GRAPHICS", + "HARDWARE", + "HYPERLINK", + "HYPERTEXT", + "INTEGER", + "INTERFACE", + "INTERNET", + "ITERATION", + "JOYSTICK", + "JUNKMAIL", + "KEYBOARD", + "KEYWORD", + "LURKING", + "MACINTOSH", + "MAINFRAME", + "MALWARE", + "MONITOR", + "NETWORK", + "NOTEBOOK", + "COMPUTER", + "OFFLINE", + "OPERATING", + "PASSWORD", + "PHISHING", + "PLATFORM", + "PODCAST", + "PRINTER", + "PRIVACY", + "PROCESS", + "PROGRAM", + "PROTOCOL", + "REALTIME", + "RESTORE", + "RUNTIME", + "SCANNER", + "SECURITY", + "SHAREWARE", + "SNAPSHOT", + "SOFTWARE", + "SPAMMER", + "SPYWARE", + "STORAGE", + "TERMINAL", + "TEMPLATE", + "TERABYTE", + "TOOLBAR", + "TYPEFACE", + "USERNAME", + "UTILITY", + "VERSION", + "VIRTUAL", + "WEBMASTER", + "WEBSITE", + "WINDOWS", + "WIRELESS", + "PROCESSOR", + ]; + return [ + words + .sort(() => Math.random() - 0.5) + .slice(0, 5) + .join(""), + keys.sort(() => Math.random() - 0.5)[0], + ]; + }, + name: "Encryption II: Vigenère Cipher", + numTries: 10, + solver: (data: [string, string], ans: string): boolean => { + // data = [plaintext, keyword] + // build char array, shifting via map and corresponding keyword letter and join to final results + const cipher = [...data[0]] + .map((a, i) => { + return a === " " + ? a + : String.fromCharCode(((a.charCodeAt(0) - 2 * 65 + data[1].charCodeAt(i % data[1].length)) % 26) + 65); + }) + .join(""); + return cipher === ans; + }, + }, ];