• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] Random Name Generator

This code is used to generate random names based on a pattern string.
JASS:
//===========================================================================
// 
// Random Name Generator
// 
//   Author: Zeatherann
//   Description: Generates random names based on the input pattern string.
// 
//===========================================================================
//***************************************************************************
//*
//*  Global Variables - These string arrays contain all the data needed for the name generator.
//*
//***************************************************************************
globals
    string array        udg_Names_v
    string array        udg_Names_V
    string array        udg_Names_B
    string array        udg_Names_c
    string array        udg_Names_C
    string array        udg_Names_s
endglobals
//***************************************************************************
//*
//*  Random Name Generator
//*
//***************************************************************************
//====================================================================================================
// NameGenerator_Initialize
//   takes   nothing
//   returns nothing
//
//   This function must be called once, before any calls to GenerateName, as it initializes the data required by that function.
//
//   NOTE: I usually make it filter out triple letters, but in order to not create dozens more string than I have to, I"ve chosen to not check this.
//====================================================================================================
function NameGenerator_Initialize takes nothing returns nothing
    set udg_Names_v[0]="a"
    set udg_Names_v[1]="e"
    set udg_Names_v[2]="i"
    set udg_Names_v[3]="o"
    set udg_Names_v[4]="u"
    set udg_Names_v[5]="y"
    set udg_Names_V[0]="a"
    set udg_Names_V[1]="ae"
    set udg_Names_V[2]="ai"
    set udg_Names_V[3]="au"
    set udg_Names_V[4]="ay"
    set udg_Names_V[5]="e"
    set udg_Names_V[6]="ea"
    set udg_Names_V[7]="ee"
    set udg_Names_V[8]="ei"
    set udg_Names_V[9]="eu"
    set udg_Names_V[10]="ey"
    set udg_Names_V[11]="i"
    set udg_Names_V[12]="ia"
    set udg_Names_V[13]="ie"
    set udg_Names_V[14]="o"
    set udg_Names_V[15]="oe"
    set udg_Names_V[16]="oi"
    set udg_Names_V[17]="oo"
    set udg_Names_V[18]="ou"
    set udg_Names_V[19]="u"
    set udg_Names_V[20]="ui"
    set udg_Names_V[21]="y"
    set udg_Names_B[0]="b"
    set udg_Names_B[1]="bl"
    set udg_Names_B[2]="br"
    set udg_Names_B[3]="c"
    set udg_Names_B[4]="ch"
    set udg_Names_B[5]="chr"
    set udg_Names_B[6]="cl"
    set udg_Names_B[7]="cr"
    set udg_Names_B[8]="d"
    set udg_Names_B[9]="dr"
    set udg_Names_B[10]="f"
    set udg_Names_B[11]="g"
    set udg_Names_B[12]="h"
    set udg_Names_B[13]="j"
    set udg_Names_B[14]="k"
    set udg_Names_B[15]="l"
    set udg_Names_B[16]="ll"
    set udg_Names_B[17]="m"
    set udg_Names_B[18]="n"
    set udg_Names_B[19]="p"
    set udg_Names_B[20]="ph"
    set udg_Names_B[21]="qu"
    set udg_Names_B[22]="r"
    set udg_Names_B[23]="rh"
    set udg_Names_B[24]="s"
    set udg_Names_B[25]="sch"
    set udg_Names_B[26]="sh"
    set udg_Names_B[27]="sl"
    set udg_Names_B[28]="sm"
    set udg_Names_B[29]="sn"
    set udg_Names_B[30]="st"
    set udg_Names_B[31]="str"
    set udg_Names_B[32]="sw"
    set udg_Names_B[33]="t"
    set udg_Names_B[34]="th"
    set udg_Names_B[35]="thr"
    set udg_Names_B[36]="tr"
    set udg_Names_B[37]="v"
    set udg_Names_B[38]="w"
    set udg_Names_B[39]="wh"
    set udg_Names_B[40]="y"
    set udg_Names_B[41]="z"
    set udg_Names_B[42]="zh"
    set udg_Names_c[0]="b"
    set udg_Names_c[1]="c"
    set udg_Names_c[2]="d"
    set udg_Names_c[3]="f"
    set udg_Names_c[4]="g"
    set udg_Names_c[5]="h"
    set udg_Names_c[6]="j"
    set udg_Names_c[7]="k"
    set udg_Names_c[8]="l"
    set udg_Names_c[9]="m"
    set udg_Names_c[10]="n"
    set udg_Names_c[11]="p"
    set udg_Names_c[12]="r"
    set udg_Names_c[13]="s"
    set udg_Names_c[14]="t"
    set udg_Names_c[15]="v"
    set udg_Names_c[16]="w"
    set udg_Names_c[17]="x"
    set udg_Names_c[18]="y"
    set udg_Names_c[19]="z"
    set udg_Names_C[0]="b"
    set udg_Names_C[1]="c"
    set udg_Names_C[2]="ch"
    set udg_Names_C[3]="ck"
    set udg_Names_C[4]="d"
    set udg_Names_C[5]="f"
    set udg_Names_C[6]="g"
    set udg_Names_C[7]="gh"
    set udg_Names_C[8]="h"
    set udg_Names_C[9]="k"
    set udg_Names_C[10]="l"
    set udg_Names_C[11]="ld"
    set udg_Names_C[12]="ll"
    set udg_Names_C[13]="lt"
    set udg_Names_C[14]="m"
    set udg_Names_C[15]="n"
    set udg_Names_C[16]="nd"
    set udg_Names_C[17]="nn"
    set udg_Names_C[18]="nt"
    set udg_Names_C[19]="p"
    set udg_Names_C[20]="ph"
    set udg_Names_C[21]="q"
    set udg_Names_C[22]="r"
    set udg_Names_C[23]="rd"
    set udg_Names_C[24]="rr"
    set udg_Names_C[25]="rt"
    set udg_Names_C[26]="s"
    set udg_Names_C[27]="sh"
    set udg_Names_C[28]="ss"
    set udg_Names_C[29]="st"
    set udg_Names_C[30]="t"
    set udg_Names_C[31]="th"
    set udg_Names_C[32]="v"
    set udg_Names_C[33]="w"
    set udg_Names_C[34]="y"
    set udg_Names_C[35]="z"
    set udg_Names_s[0]="ach"
    set udg_Names_s[1]="ack"
    set udg_Names_s[2]="ad"
    set udg_Names_s[3]="age"
    set udg_Names_s[4]="ald"
    set udg_Names_s[5]="ale"
    set udg_Names_s[6]="an"
    set udg_Names_s[7]="ang"
    set udg_Names_s[8]="ar"
    set udg_Names_s[9]="ard"
    set udg_Names_s[10]="as"
    set udg_Names_s[11]="ash"
    set udg_Names_s[12]="at"
    set udg_Names_s[13]="ath"
    set udg_Names_s[14]="augh"
    set udg_Names_s[15]="aw"
    set udg_Names_s[16]="ban"
    set udg_Names_s[17]="bel"
    set udg_Names_s[18]="bur"
    set udg_Names_s[19]="cer"
    set udg_Names_s[20]="cha"
    set udg_Names_s[21]="che"
    set udg_Names_s[22]="dan"
    set udg_Names_s[23]="dar"
    set udg_Names_s[24]="del"
    set udg_Names_s[25]="den"
    set udg_Names_s[26]="dra"
    set udg_Names_s[27]="dyn"
    set udg_Names_s[28]="ech"
    set udg_Names_s[29]="eld"
    set udg_Names_s[30]="elm"
    set udg_Names_s[31]="em"
    set udg_Names_s[32]="en"
    set udg_Names_s[33]="end"
    set udg_Names_s[34]="eng"
    set udg_Names_s[35]="enth"
    set udg_Names_s[36]="er"
    set udg_Names_s[37]="ess"
    set udg_Names_s[38]="est"
    set udg_Names_s[39]="et"
    set udg_Names_s[40]="gar"
    set udg_Names_s[41]="gha"
    set udg_Names_s[42]="hat"
    set udg_Names_s[43]="hin"
    set udg_Names_s[44]="hon"
    set udg_Names_s[45]="ia"
    set udg_Names_s[46]="ight"
    set udg_Names_s[47]="ild"
    set udg_Names_s[48]="im"
    set udg_Names_s[49]="ina"
    set udg_Names_s[50]="ine"
    set udg_Names_s[51]="ing"
    set udg_Names_s[52]="ir"
    set udg_Names_s[53]="is"
    set udg_Names_s[54]="iss"
    set udg_Names_s[55]="it"
    set udg_Names_s[56]="kal"
    set udg_Names_s[57]="kel"
    set udg_Names_s[59]="kim"
    set udg_Names_s[60]="kin"
    set udg_Names_s[61]="ler"
    set udg_Names_s[62]="lor"
    set udg_Names_s[63]="lye"
    set udg_Names_s[64]="mor"
    set udg_Names_s[65]="mos"
    set udg_Names_s[66]="nal"
    set udg_Names_s[67]="ny"
    set udg_Names_s[68]="nys"
    set udg_Names_s[69]="old"
    set udg_Names_s[70]="om"
    set udg_Names_s[71]="on"
    set udg_Names_s[72]="or"
    set udg_Names_s[73]="orm"
    set udg_Names_s[74]="os"
    set udg_Names_s[75]="ough"
    set udg_Names_s[76]="per"
    set udg_Names_s[77]="pol"
    set udg_Names_s[78]="qua"
    set udg_Names_s[79]="que"
    set udg_Names_s[80]="rad"
    set udg_Names_s[81]="rak"
    set udg_Names_s[82]="ran"
    set udg_Names_s[83]="ray"
    set udg_Names_s[84]="ril"
    set udg_Names_s[85]="ris"
    set udg_Names_s[86]="rod"
    set udg_Names_s[87]="roth"
    set udg_Names_s[88]="ryn"
    set udg_Names_s[89]="sam"
    set udg_Names_s[90]="say"
    set udg_Names_s[91]="ser"
    set udg_Names_s[92]="shy"
    set udg_Names_s[93]="skel"
    set udg_Names_s[94]="sul"
    set udg_Names_s[95]="tai"
    set udg_Names_s[96]="tan"
    set udg_Names_s[97]="tas"
    set udg_Names_s[98]="ther"
    set udg_Names_s[99]="tia"
    set udg_Names_s[100]="tin"
    set udg_Names_s[101]="ton"
    set udg_Names_s[102]="tor"
    set udg_Names_s[103]="tur"
    set udg_Names_s[104]="um"
    set udg_Names_s[105]="und"
    set udg_Names_s[106]="unt"
    set udg_Names_s[107]="urn"
    set udg_Names_s[108]="usk"
    set udg_Names_s[109]="ust"
    set udg_Names_s[110]="ver"
    set udg_Names_s[111]="ves"
    set udg_Names_s[112]="vor"
    set udg_Names_s[113]="war"
    set udg_Names_s[114]="wor"
    set udg_Names_s[115]="yer"
endfunction
//====================================================================================================
// GenerateName
//   takes   string Pattern - The string to base the form of a random name on.
//   returns string         - The randomly generated name.
//
//   This function generates a random name based on the string Pattern passed to it.
//====================================================================================================
function GenerateName takes string Pattern returns string
    local string Return=""
    local string Character
    local integer Length=StringLength(Pattern)
    local integer Index=0
    loop
        exitwhen Index==Length
        set Character=SubString(Pattern,Index,Index+1)
        if(Character=="v")then
            set Character=udg_Names_v[GetRandomInt(0,5)]
        elseif(Character=="V")then
            set Character=udg_Names_V[GetRandomInt(0,21)]
        elseif(Character=="c")then
            set Character=udg_Names_c[GetRandomInt(0,19)]
        elseif(Character=="C")then
            set Character=udg_Names_C[GetRandomInt(0,35)]
        elseif(Character=="B")then
            set Character=udg_Names_B[GetRandomInt(0,42)]
        elseif(Character=="s")then
            set Character=udg_Names_s[GetRandomInt(0,115)]
        endif
        if(Index==0)then
            set Character=StringCase(SubString(Character,0,1),true)+SubString(Character,1,StringLength(Character))
        endif
        set Return=Return+Character
        set Index=Index+1
    endloop
    return Return
endfunction
//***************************************************************************
//*
//*  Example Use
//*
//***************************************************************************
function Example_Initialize takes nothing returns nothing
    call NameGenerator_Initialize()
endfunction
function Example_Make_A_Name takes nothing returns nothing
    call BJDebugMsg(GenerateName("Bss")) // Possible output: Blirlor.
    call BJDebugMsg(GenerateName("B's-s")) // Possible output: Bl'ir-lor.
endfunction
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Would you explain how the output is determined by the input string Pattern, e.g. how does input "Bss" result in a possible output of "Blirlor."

Also, off topic, how many generate name calls would it take to significantly lag the map?
 
When the name generator comes across a character in the pattern string it checks if that character should correspond to a string array, if it does then it picks a random element from the string array. As for the lag, you'd have to look into how many string leaks are needed to lag the map. I wouldn't imagine them to lag the map but just make Warcraft III use more and more memory, which can be a problem. I wouldn't be concerned with it unless you're making thousands of names over the playthrough of the map. Obviously creating even hundreds of names at once will lag, though how much is dependant on your hardware.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
How did you determine which character n-grams to use? Most common character n-grams for fantasy names?

Personally, I would like to see a bit more NLP involved--i.e. syllable generation given an arbitrary (phonetic) alphabet and syllable constraints (e.g. Chinese can't have CCVC words in general, where as English maximally allows strengths (s)CCVCCC).

This would also make it more obvious what kind of names the user is generated--Chinese names would be more applicable to an Asian themed RPG, as the majority of the random strings generated are probably not legal phonetic strings in Chinese (or probably any East Asian language for that matter). This also applies for other themes/cultures too, e.g. European based names.
 
It's based in English, I determine the array to use based on the character in the pattern string. If you mean what values I used in the arrays then that's simple: Some are just all the permutations of letters, but they aren't my values. I used them from an existing name generator. I refrain from using natural language processing because that is a system too complex to be implemented in JASS in any effective manner. Also the structure of languages that don't share a base are hard to interchange for use with a single system. While it would be nice to see it happen, it probably never will happen. I usually make sure that the names don't have triples of a letter, but I'm trying to stay simple and reduce the creation of strings.
 
Of course it is difficult to import to a non-jngp. That's nothing easily avoidable. It also isn't customize-able because what new parts would you want to add? After I created this in C++ I've only ever added one new word (this is over a few years of use). I didn't create the current array of words mind you. How this is overkill? How would you create random names?
 
I mean explain the pattern it uses to create names.

Anyway to make the script 100% copy and paste, you could do this.

JASS:
constant function NameGenerator_Names_v takes integer index returns string
    if index == 0 then
        return "a"
    elseif index == 1 then
        return "e"
    elseif index == 2 then
        return "i"
    elseif index == 3 then
        return "o"
    elseif index == 4 then
        return "u"
    elseif index == 5 then
        return "y"
    endif
    return ""
endfunction
 
Your right, I could make this function, but the array access is still faster.
JASS:
function NameGenerator_Parts_V takes nothing returns string
    local integer Index=GetRandomInt(0,5)
    if(Index==0)then
        return "a"
    elseif(Index==1)then
        return "e"
    elseif(Index==2)then
        return "i"
    elseif(Index==3)then
        return "o"
    elseif(Index==4)then
        return "u"
    endif
    return "y"
endfunction
 
I still disagree.

First of all, once a name is generated it's usually stored. I don't see it being called that much. Even if it did I highly doubt there will be any noticeable difference.

And it's obviously not hard to create the 6 variables, it's annoying.

You're also forgetting that people will probably end up copying more than just this script. Then what? Create 3-6 variables for every JASS script when it could have been avoided with constant functions?

The only downside I see is that it will slightly increase the size of war3map.j. It will however free up a lot of memory (relatively).

If you're super focused on efficiency then use vJass.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
TH, you probably meet Zeatherann for the first time. Discussion after each of my suggestions went in the exactly same direction ^)^

Zeatherann, you have written few unique resources which hasn't been really uploaded by anyone, and varienty is good - it allows future users to choose resource which fits them best.
Don't be discouraged just because someone suggests you to look at the script of yours from different perspective.

From my own experience, I'd rather use script with lower efficiency but with better adaptation for user e.g reduced amount of code I have to write before actual operations can be performed.
You can also change the flavour of implementation via static ifs.
 

Deleted member 219079

D

Deleted member 219079

Seems nice :D

Can it produce -ill names?
e.g. Bill, Gill, Will
And extend it?
e.g. William, Billy, Willard

+rep for the unique submission
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Help me out here, please. I'm trying to find out what the difference is between c, C, v, V, s... I'm guessing v is vowel and c is consonant, but s? And what difference does the capitalization make?

Please expand the description a bit so the user knows generally what to pass through the args. I intend to approve this, but the lack of documentation is http://m.youtube.com/watch?v=07So_lJQyqw
 
Uppercase lettering usually means it's a set of what the lowercase does. So 'v' might give you "a", but 'V' could give you "ou". Likewise 'c' means consonant such as "b", but 'C' can give a consonant set such as "th". The uppercase variants contains the lowercase values as well, so 'v' and 'V' might give the same letter, like 'c' and 'C' could give the same letter. The use of the lowercase letters is for when you want a more restricted part of the name. 's' gives a syllable, and 'B' gives a syllable more suitable for the beginning of a name (hence why 'B' is capital). Does that answer your question?
 
Top