The most important thing in creating identifiably distinct cultures in a name generator is the repetition of patterns unique and common to that culture. Each culture should have a different rule and pattern set.
Here's the method I'm using in an rpg. It's not 100% procedural as it relies on a seeded data set, though there are some advantages to this, especially when the cultures themselves are not procedural and the name sets need to fit with the existing overall cultural definition that's been created.
The interesting thought is that you could build the components (generally 2-4 letters) procedurally with randomized parameters to the ruleset to define common small patterns for a new culture.
I think you'd have better results in building smaller blocks of 2-4 letters at complete random and getting something intelligible than trying to build entire names of say 3-10 letters.
Then use something like this to create the larger names. It would give a good repetition of patterns within patterns I think.
Anyway, using a manually seeded set of components for 3 cultures, my generator gives results like this:
typical western fantasy rpg theme:
male:
Ondelsric
Timtraevoc
Haldan
Bulderwyc
Aldyn
Gwydott
Indor
Meddarion
Alellot
Canradvyc
Mertrin
Birin
Oroc
Culdaerane
Ulguront
Elton
Hallonic
Dalin
Korrelas
Daloair
for this culture, masculine names will commonly start with consonants, and masculine vowels U, O, while others can appaer with varying frequency, its rare for a male to start with Y
endings are usually a shorter, sharper, harder sounds ic, oc, ot, in, on, an
female:
Eilynell
Yrila
Leria
Erisyn
Isrea
Ailrea
Gwinoa
Camorrese
Ginidira
Cylolla
Sarbral
Janiboa
Seriamyl
Salesa
Eloa
Ainryna
Anneigh
Janabea
Lyadasa
Jinedrese
feminine will more often start with vowel, commonly A, E, Y, and rarely with a masculine U, O
endings are longer, softer, more breathy, often vowel a, ia, ea, eigh, ese, el
eastern theme:
male:
Xunga lo
Chuxupo
Kamato
Xi lu
Ta' lan
Zankka
Zhago
Langkakku
Yunlachan
Hulon
Tsanchan
Tzunxichan
Lu'ga 'to
Yatnuchan
Kashan
Huxun tsu
Yannuta
Shosha lin
Xaolan tzo
Yungsu
for this culture as a whole, I've introduced the ' character as a short sharp pause marker, as well as allowing a space to break a name into further pieces.
The uncommon for western consonents X, Q, Z, W etc have been made far more common on the whole while G, H, J and such are less
masculine will rarely begin with a vowel, and Y is treated more as a consonant, with endings not as sharp and hard as the western culture but still following a U, O masculine theme as well as setting an, in to masculine
female:
Yingkime
Tsingsun
Quiyamai
Keikke 'tei
Lennirti
Zei 'te
Chikko
Qeshi lun
Onime
Xipi
Yinsi
Yitkise
Shixemi
Shikimei
Jexi le
Wenchun
Oekki 'te
Peichechen
Osesi
Quilensi
feminine more often starts with a vowel, and O in the front is considered feminine while o at the end is still masculine and uncommon.
endings are still commonly a vowel, though here it is shorter, much less breathy. frequently e, i, as well as setting en, un to feminine opposite the masculine an, in
desert theme:
male:
Zedunn
Irzaheek
Tureek
Rhavizzahd
Malonij
Kaloridd
Zahehk
Shareyidd
Sinduon
Zaddunek
Shiyad
Almorek
Talohm
Zeddsaerr
Sarruntidd
Irzim
Arrim
Salad
Suleyiir
Zemmariz
for this culture, double letters are common, rr, ii, ee, dd, mm, zz etc, and breathiness is prevailant throughout.
for masculine starters, Z, S are common consonants, while A, U, I appear for the vowels. masculine names tend to start a bit softer than males of other cultures moving to harder at the end, somewhere in the breathy mid ranges id, on, ek, un, um, iz
female:
Shayerryahn
Suayara
Seyas
Sariah
Yamallyn
Saryin
Sunyahn
Sameyahd
Shazahd
Sullorian
Maryeh
Selifahr
Sullanyah
Malahz
Seyissann
Alia
Milloh
Fahlorrloh
Zelyihn
Mina
for feminine starters Z, S are still common as with the males, though S a bit more so here. Y also appears much more frequently. endings are softer and somewhat breathier than the males, in, ahd, ahn, ah, oh, eh
and here is the code, it's quite compact and simple i think:
`Random name generator by Ortu 2-9-2013
set display mode 800,600,32
set window on
sync on
text 0,0,"loading..."
sync
dim nameParts$(1,2,2,150) `gender, race, syllable, part
dim parts$(0)
loadNameSeed("nameSeed.csv")
do
cls
x = 0
text 0,0,"Press any key to get new names"
for race = 0 to 2
inc y,20
for gender = 0 to 1
inc y,20 : text x,y,"Race "+str$(race)+" Gender "+str$(gender)
for n = 1 to 10
inc y,20 : text x,y,getName(race, gender)
next n
inc y,20 : text x,y," "
next gender
inc x,200
y = 0
next race
sync
wait key
loop
end
function loadNameSeed(file$)
`init
gender = 0
race = 0
raceCount = 1
syll = 0
`read data from file
open to read 1, file$
while file end(1) = 0
`reset temp array for holding this line
undim parts$(0)
dim parts$(0)
`parse the line to temp array
read string 1,fileLine$
`discard the first item (it is a line heading for ease of reading, un-needed for the generator)
discard$ = first token$(fileLine$,",")
repeat
p$ = next token$(",")
if p$ > ""
array insert at bottom parts$()
parts$() = p$
endif
until p$ = ""
`get a count of parsed data
indxCount = array count(parts$())
nameParts$(gender, race, syll, 0) = str$(indxCount)
`copy temp array to final array
for i = 1 to indxCount
nameParts$(gender, race, syll, i) = parts$(i)
next i
`prep for next line
gender = 1 - gender
inc syll
if syll > 2 then syll = 0
inc raceCount
if raceCount > 6
inc race
raceCount = 1
endif
endwhile
endfunction
function getName(race, gender)
`name will always pick a first and last syllable component
`randomly add a middle component or not
`+1 to the rnd result of the nameParts$() index selector to prevent picking index 0 which is used as a count flag
`-1 to max possible rnd value to offset the +1 to the result to prevent exceeding the last index which actually has a component
first$ = nameParts$(gender, race, 0, rnd(val(nameParts$(gender, race, 0, 0)) - 1) + 1)
if rnd(1) then second$ = nameParts$(gender, race, 1, rnd(val(nameParts$(gender, race, 1, 0)) - 1) + 1)
last$ = nameParts$(gender, race, 2, rnd(val(nameParts$(gender, race, 2, 0)) - 1) + 1)
name$ = first$ + second$ + last$
endfunction name$
part of the seed file as example:
WesternFemaleFirst-,Ar,Arr,Er,Err,Ail,Eil,Ain,Ein,An,Ann
WesternFemaleMiddle-,ib,a,ar,av,an,al,as,i,ir,iv
WesternFemaleLast-,wyn,win,wynn,winn,a,ia,ett,ene,eth
WesternMaleFirst-,Al,Cal,Hal,Mal,Kor,Aed,Aer,Er,Ar,Gwid
WesternMaleMiddle-,ind,and,er,ar,ond,der,dar,al,el
WesternMaleLast-,ric,roc,dyn,ion,ryn,on,in,iod,iodd,onn
DesertFemaleFirst-,Mal,Mel,Mil,Sar,Hep,Al,Sal,Sel,Sil,Sam
DesertFemaleMiddle-,ik,ir,is,iss,es,ess,as,ass,she
DesertFemaleLast-,a,yah,ia,ahd,ehd,eh,ah,az,as,yeh
DesertMaleFirst-,Mal,Sal,Al,Sam,Shar,Shal,Sar,Sun,Urd,Am
DesertMaleMiddle-,is,es,as,ast,est,on,an,un,unn,onn
DesertMaleLast-,iir,ik,ir,un,err,iz,on,iiz,iik,irr
EasternFemaleFirst-,We,Wi,Xi,Wen,Xen,Win,She,Shi,Shen,Shin
EasternFemaleMiddle-,xi,xe,xen,xin,se,si,she,shi,che,chi
EasternFemaleLast-,chun,chen, li, le, len,shen,shun, lun,sun,sen
EasternMaleFirst-,Wa,Wu,Xi,Wan,Wun,Sha,Shu,Shan,Shun,Xun
EasternMaleMiddle-,xi,xan,xa,xu,xun,sha,shu,cha,chu,cu
EasternMaleLast-,chan,chin, lo, lu, lan, lin,shin,shan,san,sin
project and seed file attached to post.
using 10 options for each part for each gender, this gives possible names:
first component & last component: 10*10 = 100
first component & middle component & last component 10*10*10 = 1000
so 1,100 possibilities per gender per race
In my full seed file, i'm using 100 options per part per gender per race giving 1,010,000 possibilites for each gender/race.
As far as randomality goes, it is a small data set with a relatively small range of possibilities, however, names are not unique. There are many Johns, Mikes, Toms etc.
An important part of defining a cultural pattern is actually the repetition of common names, and so it becomes desireable to have a large enough data set that every third name isnt the same, but that you might expect to find a couple of duplicates in 1,000.