Skip to content

Instantly share code, notes, and snippets.

@FrostBird347
Last active March 4, 2025 12:14
Show Gist options
  • Save FrostBird347/e7c017d096b3b50a75f5dcd5b4d08b99 to your computer and use it in GitHub Desktop.
Save FrostBird347/e7c017d096b3b50a75f5dcd5b4d08b99 to your computer and use it in GitHub Desktop.
Scream Cipher
// https://xkcd.com/3054/
function scream(input, padChars = false) {
let keyE = {
"A": "A",
"B": "Ȧ",
"C": "A̧",
"D": "A̠",
"E": "Á",
"F": "A̮",
"G": "A̋",
"H": "A̰",
"I": "Ả",
"J": "A̓",
"K": "Ạ",
"L": "Ă",
"M": "Ǎ",
"N": "Â",
"O": "Å",
"P": "A̯",
"Q": "A̤",
"R": "Ȃ",
"S": "Ã",
"T": "Ā", //Wasn't sure if it was 'Ā' or 'A̅' so I just copied Ā from the panel's hover text
"U": "Ä",
"V": "À",
"W": "Ȁ",
"X": "A̽",
"Y": "A̦",
"Z": "A̷" //Could be 'A̸' or 'A̷', im guessing it's A̷
};
let keyD = {
//Add those uncertain keys to the decoder
"A̸": "Z",
"A̅": "T",
//Add decoding support for some other implementations that avoid combining characters (even though they are used in the panel's hover text)
"Ȧ": "B",
"Á": "E",
"Ả": "I",
"Ạ": "K",
"Ă": "L",
"Ǎ": "M",
"Â": "N",
"Å": "O",
"Ȃ": "R",
"Ã": "S",
"Ā": "T",
"Ä": "U",
"À": "V",
"Ȁ": "W",
"Ⱥ": "Z",
//Have seen some other people also use these characters instead
"A̱": "D",
"A̲": "D",
"Aͯ": "X",
"A̡": "C"
};
//Use the encoder key to fill out the rest of the decoder key
for (let i = 0, tmp = Object.keys(keyE); i < tmp.length; i++) {
keyD[keyE[tmp[i]]] = tmp[i];
//This seems to slightly improve the chances of an encoded message not getting obliterated when sent in discord
if (padChars && tmp[i] != "A") {
keyE[tmp[i]] += '​';
}
}
//Too lazy to check if it should be encoded or decoded so we just do both
let eOut = "";
let dOut = "";
let splitIn = input.toUpperCase().split("");
for (let i = 0; i < splitIn.length; i++) {
//If input is in dictionary add value, otherwise add input
eOut += (keyE[splitIn[i]] != undefined) ? keyE[splitIn[i]] : splitIn[i];
//If the input is 'A' then we need to check the next character before assuming it's just an 'A'
if (splitIn[i] == "A") {
let tmp = splitIn[i] + splitIn[i + 1];
if (keyD[tmp] != undefined) {
dOut += keyD[tmp];
//Increment the index by 1 to skip over the combining character on the next loop
i++;
//But make sure the skipped char is still encoded to prevent a message from being corrupted if it's encoded a second time
eOut += (keyE[splitIn[i]] != undefined) ? keyE[splitIn[i]] : splitIn[i];
} else {
dOut += "A";
}
} else {
dOut += (keyD[splitIn[i]] != undefined) ? keyD[splitIn[i]] : splitIn[i];
}
}
return {encoded: eOut, decoded: dOut};
}
console.log("scream.js loaded, use scream(\"input\") in your code!\nwritten by FrostBird347, licensed under MIT");
console.log(scream("test message").encoded);
console.log(scream("ĀÁÃĀ ǍÁÃÃAA̋Á").decoded);
@FrostBird347
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment