/////////////////////////////////////////////////////////////////////////// // Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasListReverse(list lst) { if (llGetListLength(lst) <= 1) return lst; return wasListReverse( llList2List( lst, 1, llGetListLength(lst) ) ) + llList2List(lst, 0, 0); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasForwardPermuteListElements(list input, integer times) { if(times == 0) return input; return wasForwardPermuteListElements( llList2String(input, -1) + llList2List(input, 0, -2), --times ); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer wasIsUpper(string a) { if(a == "") return FALSE; integer x = llBase64ToInteger("AAAA" + llStringToBase64(llGetSubString(a, 0, 0))); return x >= 65 && x <= 90; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer wasIsAlpha(string a) { if(a == "") return FALSE; integer x = llBase64ToInteger("AAAA" + llStringToBase64(llGetSubString(a, 0, 0))); return (x >= 65 && x <= 90) || (x >= 97 && x <= 122); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasListPermuteToElement(list rot, string ring) { if(ring == llList2String(rot, 0)) return rot; integer i = llListFindList(rot, (list)ring); return ring + llList2List( llDeleteSubList( rot, i, i ), i, -1 ) + llList2List( llDeleteSubList( rot, i+1, -1 ), 0, i-1 ); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// // Symmetrically encrypts or decrypts a message using the Enigma cypher // using the Wizardry and Steamworks variation of the Enigma machine. // // Parameters: // message - a message to encrypt or decrypt. // These two lists have to be of equal length: // rotors - a list of rotors which can contain any selection of: 1, 2, // 3, 4, 5, 6, 7, 8, b or g in any order. // plugs - the initial plugs settings, a list of letters of the // alphabet for every selected rotor. // reflector - a single letter reflector, can be either: B, b, C, c // // Example; llOwnerSay( // wasEngima( // "Good day!", // message to encrypt or decrypt // ["3", "g", "1"], // rotors 3, g and 1 // ["z", "p", "q"], // plugs z, p and q // b // reflector b // ) // ); string wasENIGMA(string message, list rotors, list plugs, string reflector) { // Ten rotors in total: 1 2 3 4 5 6 7 8 b g list def_rotors = [ "1", "e", "k", "m", "f", "l", "g", "d", "q", "v", "z", "n", "t", "o", "w", "y", "h", "x", "u", "s", "p", "a", "i", "b", "r", "c", "j", "2", "a", "j", "d", "k", "s", "i", "r", "u", "x", "b", "l", "h", "w", "t", "m", "c", "q", "g", "z", "n", "p", "y", "f", "v", "o", "e", "3", "b", "d", "f", "h", "j", "l", "c", "p", "r", "t", "x", "v", "z", "n", "y", "e", "i", "w", "g", "a", "k", "m", "u", "s", "q", "o", "4", "e", "s", "o", "v", "p", "z", "j", "a", "y", "q", "u", "i", "r", "h", "x", "l", "n", "f", "t", "g", "k", "d", "c", "m", "w", "b", "5", "v", "z", "b", "r", "g", "i", "t", "y", "u", "p", "s", "d", "n", "h", "l", "x", "a", "w", "m", "j", "q", "o", "f", "e", "c", "k", "6", "j", "p", "g", "v", "o", "u", "m", "f", "y", "q", "b", "e", "n", "h", "z", "r", "d", "k", "a", "s", "x", "l", "i", "c", "t", "w", "7", "n", "z", "j", "h", "g", "r", "c", "x", "m", "y", "s", "w", "b", "o", "u", "f", "a", "i", "v", "l", "p", "e", "k", "q", "d", "t", "8", "f", "k", "q", "h", "t", "l", "x", "o", "c", "b", "j", "s", "p", "d", "z", "r", "a", "m", "e", "w", "n", "i", "u", "y", "g", "v", "b", "l", "e", "y", "j", "v", "c", "n", "i", "x", "w", "p", "b", "q", "m", "d", "r", "t", "a", "k", "z", "g", "f", "u", "h", "o", "s", "g", "f", "s", "o", "k", "a", "n", "u", "e", "r", "h", "m", "b", "t", "i", "y", "c", "w", "l", "q", "p", "z", "x", "v", "g", "j", "d" ]; // Four reflectors: B C b c list def_reflectors = [ "B", "a", "y", "b", "r", "c", "u", "d", "h", "e", "q", "f", "s", "g", "l", "i", "p", "j", "x", "k", "n", "m", "o", "t", "z", "v", "w", "C", "a", "f", "b", "v", "c", "p", "d", "j", "e", "i", "g", "o", "h", "y", "k", "r", "l", "z", "m", "x", "n", "w", "t", "q", "s", "u", "b", "a", "e", "b", "n", "c", "k", "d", "q", "f", "u", "g", "y", "h", "w", "i", "j", "l", "o", "m", "p", "r", "x", "s", "z", "t", "v", "c", "a", "r", "b", "d", "c", "o", "e", "j", "f", "n", "g", "t", "h", "k", "i", "v", "l", "m", "p", "w", "q", "z", "s", "x", "u", "y" ]; // Set-up rotors from plugs settings do { string rotor = llToLower( llList2String( rotors, 0 ) ); // Determine which rotor is used. integer i = llListFindList( llList2ListStrided( def_rotors, 0, -1, 27 ), (list)rotor ); // And permute to the plugs setting. def_rotors = llListReplaceList( def_rotors, wasListPermuteToElement( llList2List( def_rotors, i*27+1, i*27+26 ), llToLower( llList2String( plugs, 0 ) ) ), i*27+1, i*27+26 ); // We do not need rings anymore so discard the list plugs = llDeleteSubList(plugs, 0, 0); // We still need rotors so permute them rotors = llDeleteSubList(rotors, 0, 0); rotors += rotor; } while (llGetListLength(plugs) != 0); // Setjmp :-) string setjmp; // Now encrypt or decrypt. string result = ""; do { // Get a character. string c = llGetSubString(message, 0, 0); // If it is not an alphabetic character, add it to the result and continue. if (!wasIsAlpha(c)) { result += c; jump input; } // Convert the character to lower case. string r = llToLower(c); // Forward pass through the Enigma setjmp = "forward"; jump longjmp; @forward; // Reflect integer j = llListFindList(llList2ListStrided(def_reflectors, 0, -1, 27), (list)reflector); list reflector = llList2List(def_reflectors, j*27+1, j*27+26); integer a = llListFindList(reflector, (list)r); if((a+1)%2 == 0) { r = llList2String(reflector, a - 1); jump reflect; } r = llList2String(reflector, a + 1); @reflect; // Reverse the rotors. rotors = wasListReverse(rotors); // Reverse pass through the Enigma setjmp = "reverse"; jump longjmp; @reverse; if (wasIsUpper(c)) { r = llToUpper(r); } result += r; @input; message = llDeleteSubString(message, 0, 0); jump continue; @longjmp; // Rotor pass through the Enigma. integer i = llGetListLength(rotors) - 1; do { // Determine the first rotor. string p = llToLower( llList2String( rotors, 0 ) ); integer n = llListFindList( llList2ListStrided( def_rotors, 0, -1, 27 ), (list)p ); list rotor = llList2List( def_rotors, n*27+1, n*27+26 ); // Rotate the rotor. def_rotors = llListReplaceList( def_rotors, wasForwardPermuteListElements( rotor, 1 ), n*27+1, n*27+26 ); if(i != 0) { // Get the index of the character. integer x = llListFindList( rotor, (list)r ); // Determine the second rotor. n = llListFindList( llList2ListStrided( def_rotors, 0, -1, 27 ), (list)llToLower( llList2String( rotors, 1 ) ) ); // Set the index. r = llList2String( llList2List( def_rotors, n*27+1, n*27+26 ), x ); } // Permute rotors rotors = llDeleteSubList(rotors, 0, 0); rotors += p; --i; } while (i > -1); // jump table if(setjmp == "forward") jump forward; if(setjmp == "reverse") jump reverse; @continue; } while (llStringLength(message) != 0); return result; } default { state_entry() { llOwnerSay( wasENIGMA( wasENIGMA( "Good day, how are you?", [ "1", "3", "b" ], [ "q", "r", "z" ], "c" ), [ "1", "3", "b" ], [ "q", "r", "z" ], "c" ) ); } }