Files
Paradise/code/modules/mob/language.dm
Tigercat2000 71e5344a98 Mass replace
2016-07-07 19:34:02 -07:00

663 lines
22 KiB
Plaintext

#define SCRAMBLE_CACHE_LEN 20
/*
Datum based languages. Easily editable and modular.
*/
/datum/language
var/name = "an unknown language" // Fluff name of language if any.
var/desc = "A language." // Short description for 'Check Languages'.
var/speech_verb = "says" // 'says', 'hisses', 'farts'.
var/ask_verb = "asks" // Used when sentence ends in a ?
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead.
var/signlang_verb = list() // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
var/colour = "body" // CSS style to use for strings in this language.
var/key = "x" // Character used to speak in language eg. :o for Unathi.
var/flags = 0 // Various language flags.
var/native // If set, non-native speakers will have trouble speaking.
var/list/syllables // Used when scrambling text for a non-speaker.
var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string.
var/follow = 0 // Applies to HIVEMIND languages - should a follow link be included for dead mobs?
var/english_names = 0 // Do we want English names by default, no matter what?
var/list/scramble_cache = list()
/datum/language/proc/get_random_name(var/gender, name_count=2, syllable_count=4)
if(!syllables || !syllables.len || english_names)
if(gender==FEMALE)
return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
else
return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
var/full_name = ""
var/new_name = ""
for(var/i = 0;i<name_count;i++)
new_name = ""
for(var/x = rand(Floor(syllable_count/2),syllable_count);x>0;x--)
new_name += pick(syllables)
full_name += " [capitalize(lowertext(new_name))]"
return "[trim(full_name)]"
/datum/language/proc/scramble(var/input)
if(!syllables || !syllables.len)
return stars(input)
// If the input is cached already, move it to the end of the cache and return it
if(input in scramble_cache)
var/n = scramble_cache[input]
scramble_cache -= input
scramble_cache[input] = n
return n
var/input_size = length(input)
var/scrambled_text = ""
var/capitalize = 1
while(length(scrambled_text) < input_size)
var/next = pick(syllables)
if(capitalize)
next = capitalize(next)
capitalize = 0
scrambled_text += next
var/chance = rand(100)
if(chance <= 5)
scrambled_text += ". "
capitalize = 1
else if(chance > 5 && chance <= space_chance)
scrambled_text += " "
scrambled_text = trim(scrambled_text)
var/ending = copytext(scrambled_text, length(scrambled_text))
if(ending == ".")
scrambled_text = copytext(scrambled_text,1,length(scrambled_text)-1)
var/input_ending = copytext(input, input_size)
if(input_ending in list("!","?","."))
scrambled_text += input_ending
// Add it to cache, cutting old entries if the list is too long
scramble_cache[input] = scrambled_text
if(scramble_cache.len > SCRAMBLE_CACHE_LEN)
scramble_cache.Cut(1, scramble_cache.len-SCRAMBLE_CACHE_LEN-1)
return scrambled_text
/datum/language/proc/format_message(message, verb)
return "[verb], <span class='message'><span class='[colour]'>\"[capitalize(message)]\"</span></span>"
/datum/language/proc/format_message_radio(message, verb)
return "[verb], <span class='[colour]'>\"[capitalize(message)]\"</span>"
/datum/language/proc/get_talkinto_msg_range(message)
// if you yell, you'll be heard from two tiles over instead of one
return (copytext(message, length(message)) == "!") ? 2 : 1
/datum/language/proc/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
log_say("[key_name(speaker)]: ([name]) [message]")
if(!speaker_mask) speaker_mask = speaker.name
var/msg = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> [format_message(message, get_spoken_verb(message))]</span></i>"
for(var/mob/player in player_list)
if(istype(player,/mob/dead) && follow)
var/msg_dead = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> ([ghost_follow_link(speaker, ghost=player)]) [format_message(message, get_spoken_verb(message))]</span></i>"
to_chat(player, msg_dead)
continue
else if(istype(player,/mob/dead) || ((src in player.languages) && check_special_condition(player, speaker)))
to_chat(player, msg)
/datum/language/proc/check_special_condition(var/mob/other, var/mob/living/speaker)
return 1
/datum/language/proc/get_spoken_verb(var/msg_end)
switch(msg_end)
if("!")
return exclaim_verb
if("?")
return ask_verb
return speech_verb
// Noise "language", for audible emotes.
/datum/language/noise
name = "Noise"
desc = "Noises"
key = ""
flags = RESTRICTED|NONGLOBAL|INNATE|NO_TALK_MSG|NO_STUTTER
/datum/language/noise/format_message(message, verb)
return "<span class='message'><span class='[colour]'>[message]</span></span>"
/datum/language/noise/format_message_radio(message, verb)
return "<span class='[colour]'>[message]</span>"
/datum/language/noise/get_talkinto_msg_range(message)
// if you make a loud noise (screams etc), you'll be heard from 4 tiles over instead of two
return (copytext(message, length(message)) == "!") ? 4 : 2
/datum/language/unathi
name = "Sinta'unathi"
desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi."
speech_verb = "hisses"
ask_verb = "hisses"
exclaim_verb = "roars"
colour = "soghun"
key = "o"
flags = RESTRICTED
syllables = list("ss","ss","ss","ss","skak","seeki","resh","las","esi","kor","sh")
/datum/language/unathi/get_random_name()
var/new_name = ..()
while(findtextEx(new_name,"sss",1,null))
new_name = replacetext(new_name, "sss", "ss")
return capitalize(new_name)
/datum/language/tajaran
name = "Siik'tajr"
desc = "The traditionally employed tongue of Ahdomai, composed of expressive yowls and chirps. Native to the Tajaran."
speech_verb = "mrowls"
ask_verb = "mrowls"
exclaim_verb = "yowls"
colour = "tajaran"
key = "j"
flags = RESTRICTED
syllables = list("rr","rr","tajr","kir","raj","kii","mir","kra","ahk","nal","vah","khaz","jri","ran","darr", \
"mi","jri","dynh","manq","rhe","zar","rrhaz","kal","chur","eech","thaa","dra","jurl","mah","sanu","dra","ii'r", \
"ka","aasi","far","wa","baq","ara","qara","zir","sam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", \
"hal","ket","jurl","mah","tul","cresh","azu","ragh")
/datum/language/tajaran/get_random_name(var/gender)
var/new_name = ..(gender,1)
if(prob(80))
new_name += " [pick(list("Hadii","Kaytam","Zhan-Khazan","Hharar","Njarir'Akhan"))]"
else
new_name += ..(gender,1)
return new_name
/datum/language/vulpkanin
name = "Canilunzt"
desc = "The guttural language spoken and utilized by the inhabitants of Vazzend system, composed of growls, barks, yaps, and heavy utilization of ears and tail movements.Vulpkanin speak this language with ease."
speech_verb = "rawrs"
ask_verb = "rurs"
exclaim_verb = "barks"
colour = "vulpkanin"
key = "7"
flags = RESTRICTED
syllables = list("rur","ya","cen","rawr","bar","kuk","tek","qat","uk","wu","vuh","tah","tch","schz","auch", \
"ist","ein","entch","zwichs","tut","mir","wo","bis","es","vor","nic","gro","lll","enem","zandt","tzch","noch", \
"hel","ischt","far","wa","baram","iereng","tech","lach","sam","mak","lich","gen","or","ag","eck","gec","stag","onn", \
"bin","ket","jarl","vulf","einech","cresthz","azunein","ghzth")
/datum/language/skrell
name = "Skrellian"
desc = "A melodic and complex language spoken by the Skrell of Qerrbalak. Some of the notes are inaudible to humans."
speech_verb = "warbles"
ask_verb = "warbles"
exclaim_verb = "warbles"
colour = "skrell"
key = "k"
flags = RESTRICTED
syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!")
/datum/language/vox
name = "Vox-pidgin"
desc = "The common tongue of the various Vox ships making up the Shoal. It sounds like chaotic shrieking to everyone else."
speech_verb = "shrieks"
ask_verb = "creels"
exclaim_verb = "SHRIEKS"
colour = "vox"
key = "v"
flags = RESTRICTED | WHITELISTED
syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya", "yi", "chi","cha","kah", \
"SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA")
/datum/language/vox/get_random_name()
return ..(FEMALE,1,6)
/datum/language/diona
name = "Rootspeak"
desc = "A creaking, subvocal language spoken instinctively by the Dionaea. Due to the unique makeup of the average Diona, a phrase of Rootspeak can be a combination of anywhere from one to twelve individual voices and notes."
speech_verb = "creaks and rustles"
ask_verb = "creaks"
exclaim_verb = "rustles"
colour = "diona"
key = "q"
flags = RESTRICTED
syllables = list("hs","zt","kr","st","sh")
/datum/language/diona/get_random_name()
var/new_name = "[pick(list("To Sleep Beneath","Wind Over","Embrace of","Dreams of","Witnessing","To Walk Beneath","Approaching the"))]"
new_name += " [pick(list("the Void","the Sky","Encroaching Night","Planetsong","Starsong","the Wandering Star","the Empty Day","Daybreak","Nightfall","the Rain"))]"
return new_name
/datum/language/trinary
name = "Trinary"
desc = "A modification of binary to allow fuzzy logic. 0 is no, 1 is maybe, 2 is yes. Credited with giving Machine People the ability to think creatively."
speech_verb = "states"
ask_verb = "queries"
exclaim_verb = "exclaims"
colour = "trinary"
key = "5"
flags = RESTRICTED | WHITELISTED
syllables = list("02011","01222","10100","10210","21012","02011","21200","1002","2001","0002","0012","0012","000","120","121","201","220","10","11","0")
/datum/language/trinary/get_random_name()
var/new_name
if(prob(70))
new_name = "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]"
else
new_name = pick(ai_names)
return new_name
/datum/language/kidan
name = "Chittin"
desc = "The noise made by rubbing its antennae together is actually a complex form of communication for Kidan."
speech_verb = "rubs its antennae together"
ask_verb = "rubs its antennae together"
exclaim_verb = "rubs its antennae together"
colour = "kidan"
key = "4"
flags = RESTRICTED | WHITELISTED
syllables = list("click","clack")
/datum/language/slime
name = "Bubblish"
desc = "The language of slimes. It's a mixture of bubbling noises and pops. Very difficult to speak without mechanical aid for humans."
speech_verb = "bubbles and pops"
ask_verb = "bubbles and pops"
exclaim_verb = "bubbles and pops"
colour = "slime"
key = "f"
flags = RESTRICTED | WHITELISTED
syllables = list("blob","plop","pop","bop","boop")
/datum/language/drask
name = "Orluum"
desc = "The droning, vibrous language of the Drask. It sounds somewhat like whalesong."
speech_verb = "drones"
ask_verb = "hums"
exclaim_verb = "rumbles"
colour = "drask"
key = "%"
flags = RESTRICTED | WHITELISTED
syllables = list("hoorb","vrrm","ooorm","urrrum","ooum","ee","ffm","hhh","mn","ongg")
/datum/language/drask/get_random_name()
var/new_name = "[pick(list("Hoorm","Viisk","Saar","Mnoo","Oumn","Fmong","Gnii","Vrrm","Oorm","Dromnn","Ssooumn","Ovv", "Hoorb","Vaar","Gaar","Goom","Ruum","Rumum"))]"
new_name += "-[pick(list("Hoorm","Viisk","Saar","Mnoo","Oumn","Fmong","Gnii","Vrrm","Oorm","Dromnn","Ssooumn","Ovv", "Hoorb","Vaar","Gaar","Goom","Ruum","Rumum"))]"
new_name += "-[pick(list("Hoorm","Viisk","Saar","Mnoo","Oumn","Fmong","Gnii","Vrrm","Oorm","Dromnn","Ssooumn","Ovv", "Hoorb","Vaar","Gaar","Goom","Ruum","Rumum"))]"
return new_name
/datum/language/common
name = "Galactic Common"
desc = "The common galactic tongue."
speech_verb = "says"
whisper_verb = "whispers"
key = "9"
flags = RESTRICTED
syllables = list("blah","blah","blah","bleh","meh","neh","nah","wah")
english_names = 1
//TODO flag certain languages to use the mob-type specific say_quote and then get rid of these.
/datum/language/common/get_spoken_verb(var/msg_end)
switch(msg_end)
if("!")
return pick("exclaims","shouts","yells") //TODO: make the basic proc handle lists of verbs.
if("?")
return ask_verb
return speech_verb
/datum/language/human
name = "Sol Common"
desc = "A bastardized hybrid of informal English and elements of Mandarin Chinese; the common language of the Sol system."
speech_verb = "says"
whisper_verb = "whispers"
colour = "solcom"
key = "1"
flags = RESTRICTED
syllables = list("tao","shi","tzu","yi","com","be","is","i","op","vi","ed","lec","mo","cle","te","dis","e")
english_names = 1
/datum/language/human/get_spoken_verb(var/msg_end)
switch(msg_end)
if("!")
return pick("exclaims","shouts","yells") //TODO: make the basic proc handle lists of verbs.
if("?")
return ask_verb
return speech_verb
// Galactic common languages (systemwide accepted standards).
/datum/language/trader
name = "Tradeband"
desc = "Maintained by the various trading cartels in major systems, this elegant, structured language is used for bartering and bargaining."
speech_verb = "enunciates"
colour = "say_quote"
key = "2"
space_chance = 100
syllables = list("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit",
"sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore",
"magna", "aliqua", "ut", "enim", "ad", "minim", "veniam", "quis", "nostrud",
"exercitation", "ullamco", "laboris", "nisi", "ut", "aliquip", "ex", "ea", "commodo",
"consequat", "duis", "aute", "irure", "dolor", "in", "reprehenderit", "in",
"voluptate", "velit", "esse", "cillum", "dolore", "eu", "fugiat", "nulla",
"pariatur", "excepteur", "sint", "occaecat", "cupidatat", "non", "proident", "sunt",
"in", "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum")
/datum/language/gutter
name = "Gutter"
desc = "Much like Standard, this crude pidgin tongue descended from numerous languages and serves as Tradeband for criminal elements."
speech_verb = "growls"
ask_verb = "gnarls"
exclaim_verb = "snarls"
colour = "gutter"
key = "3"
syllables = list ("gra","ba","ba","breh","bra","rah","dur","ra","ro","gro","go","ber","bar","geh","heh", "gra")
/datum/language/clown
name = "Clownish"
desc = "The language of clown planet. Mother tongue of clowns throughout the Galaxy."
speech_verb = "honks"
ask_verb = "honks"
exclaim_verb = "honks"
colour = "clown"
key = "0"
syllables = list ("honk","squeak","bonk","toot","narf","zub","wee","wub","norf")
/datum/language/wryn
name = "Wryn Hivemind"
desc = "Wryn have the strange ability to commune over a psychic hivemind."
speech_verb = "chitters"
ask_verb = "chitters"
exclaim_verb = "chitters"
colour = "alien"
key = "y"
flags = RESTRICTED | HIVEMIND
/datum/language/wryn/check_special_condition(var/mob/other)
var/mob/living/carbon/M = other
if(!istype(M))
return 1
if(locate(/obj/item/organ/internal/wryn/hivenode) in M.internal_organs)
return 1
return 0
/datum/language/xenocommon
name = "Xenomorph"
colour = "alien"
desc = "The common tongue of the xenomorphs."
speech_verb = "hisses"
ask_verb = "hisses"
exclaim_verb = "hisses"
key = "6"
flags = RESTRICTED
syllables = list("sss","sSs","SSS")
/datum/language/xenos
name = "Hivemind"
desc = "Xenomorphs have the strange ability to commune over a psychic hivemind."
speech_verb = "hisses"
ask_verb = "hisses"
exclaim_verb = "hisses"
colour = "alien"
key = "a"
flags = RESTRICTED | HIVEMIND
follow = 1
/datum/language/ling
name = "Changeling"
desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance."
speech_verb = "says"
colour = "changeling"
key = "g"
flags = RESTRICTED | HIVEMIND
/datum/language/shadowling
name = "Shadowling Hivemind"
desc = "Shadowlings and their thralls are capable of communicating over a psychic hivemind."
speech_verb = "says"
colour = "shadowling"
key = "8"
flags = RESTRICTED | HIVEMIND
/datum/language/shadowling/broadcast(var/mob/living/speaker, var/message, var/speaker_mask)
if(speaker.mind && speaker.mind.special_role)
..(speaker, message, "([speaker.mind.special_role]) [speaker]")
else
..(speaker, message)
/datum/language/ling/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
if(speaker.mind && speaker.mind.changeling)
..(speaker,message,speaker.mind.changeling.changelingID)
else
..(speaker,message)
/datum/language/abductor
name = "Abductor Mindlink"
desc = "Abductors are incapable of speech, but have a psychic link attuned to their own team."
speech_verb = "gibbers"
ask_verb = "gibbers"
exclaim_verb = "gibbers"
colour = "abductor"
key = "zw" //doesn't matter, this is their default and only language
flags = RESTRICTED | HIVEMIND
/datum/language/abductor/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
..(speaker,message,speaker.real_name)
/datum/language/abductor/check_special_condition(var/mob/living/carbon/human/other, var/mob/living/carbon/human/speaker)
if(other.mind && other.mind.abductor)
if(other.mind.abductor.team == speaker.mind.abductor.team)
return 1
return 0
/datum/language/corticalborer
name = "Cortical Link"
desc = "Cortical borers possess a strange link between their tiny minds."
speech_verb = "sings"
ask_verb = "sings"
exclaim_verb = "sings"
colour = "alien"
key = "x"
flags = RESTRICTED | HIVEMIND
/datum/language/corticalborer/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
var/mob/living/simple_animal/borer/B
if(istype(speaker,/mob/living/carbon))
var/mob/living/carbon/M = speaker
B = M.has_brain_worms()
else if(istype(speaker,/mob/living/simple_animal/borer))
B = speaker
if(B)
speaker_mask = B.truename
..(speaker,message,speaker_mask)
/datum/language/binary
name = "Robot Talk"
desc = "Most human stations support free-use communications protocols and routing hubs for synthetic use."
colour = "say_quote"
speech_verb = "states"
ask_verb = "queries"
exclaim_verb = "declares"
key = "b"
flags = RESTRICTED | HIVEMIND
follow = 1
var/drone_only
/datum/language/binary/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
if(!speaker.binarycheck())
return
if(!message)
return
var/message_start = "<i><span class='game say'>[name], <span class='name'>[speaker.name]</span>"
var/message_body = "<span class='message'>[speaker.say_quote(message)], \"[message]\"</span></span></i>"
for(var/mob/M in dead_mob_list)
if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain))
var/message_start_dead = "<i><span class='game say'>[name], <span class='name'>[speaker.name] ([ghost_follow_link(speaker, ghost=M)])</span>"
M.show_message("[message_start_dead] [message_body]", 2)
for(var/mob/living/S in living_mob_list)
if(drone_only && !istype(S,/mob/living/silicon/robot/drone))
continue
else if(istype(S , /mob/living/silicon/ai))
message_start = "<i><span class='game say'>[name], <a href='byond://?src=\ref[S];track=\ref[speaker]'><span class='name'>[speaker.name]</span></a>"
else if(!S.binarycheck())
continue
S.show_message("[message_start] [message_body]", 2)
var/list/listening = hearers(1, src)
listening -= src
for(var/mob/living/M in listening)
if(istype(M, /mob/living/silicon) || M.binarycheck())
continue
M.show_message("<i><span class='game say'><span class='name'>synthesised voice</span> <span class='message'>beeps, \"beep beep beep\"</span></span></i>",2)
//robot binary xmitter component power usage
if(isrobot(speaker))
var/mob/living/silicon/robot/R = speaker
var/datum/robot_component/C = R.components["comms"]
R.use_power(C.energy_consumption)
/datum/language/binary/drone
name = "Drone Talk"
desc = "A heavily encoded damage control coordination stream."
speech_verb = "transmits"
ask_verb = "transmits"
exclaim_verb = "transmits"
colour = "say_quote"
key = "d"
flags = RESTRICTED | HIVEMIND
drone_only = 1
follow = 1
/datum/language/swarmer
name = "Swarmer"
desc = "A heavily encoded alien binary pattern."
speech_verb = "tones"
ask_verb = "tones"
exclaim_verb = "tones"
colour = "say_quote"
key = "z"//Zwarmer...Or Zerg!
flags = RESTRICTED || HIVEMIND
follow = 1
// Language handling.
/mob/proc/add_language(var/language)
var/datum/language/new_language = all_languages[language]
if(!istype(new_language) || new_language in languages)
return 0
languages |= new_language
return 1
/mob/proc/remove_language(var/rem_language)
var/datum/language/L = all_languages[rem_language]
. = (L in languages)
languages.Remove(L)
/mob/living/remove_language(rem_language)
var/datum/language/L = all_languages[rem_language]
if(default_language == L)
default_language = null
return ..()
// Can we speak this language, as opposed to just understanding it?
/mob/proc/can_speak(datum/language/speaking)
return (universal_speak || (speaking && speaking.flags & INNATE) || speaking in src.languages)
//TBD
/mob/verb/check_languages()
set name = "Check Known Languages"
set category = "IC"
set src = usr
var/dat = "<b><font size = 5>Known Languages</font></b><br/><br/>"
for(var/datum/language/L in languages)
if(!(L.flags & NONGLOBAL))
dat += "<b>[L.name] (:[L.key])</b><br/>[L.desc]<br/><br/>"
src << browse(dat, "window=checklanguage")
return
/mob/living/check_languages()
var/dat = "<b><font size = 5>Known Languages</font></b><br/><br/>"
if(default_language)
dat += "Current default language: [default_language] - <a href='byond://?src=\ref[src];default_lang=reset'>reset</a><br/><br/>"
for(var/datum/language/L in languages)
if(!(L.flags & NONGLOBAL))
if(L == default_language)
dat += "<b>[L.name] (:[L.key])</b> - default - <a href='byond://?src=\ref[src];default_lang=reset'>reset</a><br/>[L.desc]<br/><br/>"
else
dat += "<b>[L.name] (:[L.key])</b> - <a href=\"byond://?src=\ref[src];default_lang=[L]\">set default</a><br/>[L.desc]<br/><br/>"
src << browse(dat, "window=checklanguage")
/mob/living/Topic(href, href_list)
if(href_list["default_lang"])
if(href_list["default_lang"] == "reset")
set_default_language(null)
else
var/datum/language/L = all_languages[href_list["default_lang"]]
if(L)
set_default_language(L)
check_languages()
return 1
else
return ..()
/datum/language/human/monkey
name = "Chimpanzee"
desc = "Ook ook ook."
speech_verb = "chimpers"
ask_verb = "chimpers"
exclaim_verb = "screeches"
key = "mo"
/datum/language/skrell/monkey
name = "Neara"
desc = "Squik squik squik."
key = "ne"
/datum/language/unathi/monkey
name = "Stok"
desc = "Hiss hiss hiss."
key = "st"
/datum/language/tajaran/monkey
name = "Farwa"
desc = "Meow meow meow."
key = "fa"
/datum/language/vulpkanin/monkey
name = "Wolpin"
desc = "Bark bark bark."
key = "vu"
#undef SCRAMBLE_CACHE_LEN