Data Driven Random Name Generation In Python

In Tiny Tyranny, one of my goals is to cultivate attachment between players and their characters. One way to do this is to individualize the characters by providing names for them. This helps elevate them from throwaway troops to something memorable. (Letting players name characters themselves can help generate this effect too – see XCOM).

Another goal for Tiny Tyranny is to let players mod all aspects of it. This includes letting modders add new characters, monsters, places, and factions. Therefore, the name generators need to be moddable too.

I just finished coding the way data driven name generators work in Tiny Tyranny.

After the jump, my code and sample name generator file for human male fighter characters, like the lovely human captain (shown above) .

word
prefix
Iss
Grieg
Ky
Sam
Ash
Ler
Mat
Matt
Hen
Pet
Jod
Jad
Jar
Jim
Yel
syllable
ild
erv
ton
ach
thryn
thrin
em
hin
suffix
er
rich
rick
tian
son
sin
stan
stin
styn
ino
ero
mir
imir
stan
word
prefix
Chris
Dav
Brown
Far
All
Black
Mull
Simp
Mort
Fult
Mc
Barn
Mill
syllable
id
ing
laugh
suffix
tian
son
ing
en
well
son
ston
stan
brun
on
ler

Basically what we have here is a list that gets translated into two word generators (the text ‘word’ indicates the start of a new word generator). Word generators are made up of up to three parts – prefixes, syllables, and suffixes. These are where the magic happens – for the most part anyway. Word lengths are generated according to a pretty boring distribution that weights short words more heavily. Here’s my class in Python.

class WordGenerator:
    def __init__(self):
        self.prefixes = []
        self.syllables = []
        self.suffixes = []
 
    def getWord(self):
        prefix = random.choice(self.prefixes)
        word = prefix
        if len(self.syllables) > 1:
            numSyllables = random.choice([0, 0, 0, 0, 1, 1, 1, 2, 2, 3])
            for i in range(0,numSyllables):
                word = word + random.choice(self.syllables)
        if len(self.suffixes) > 1:
            word = word + random.choice(self.suffixes)
        return word

Next up is the name generator. The name generator contains all the word generators and simply uses them to generate the different words that make up a name. It’s also responsible for parsing the files containing all the parts of names the name generator can use. Here’s the name generator source.

class NameGenerator:
    def __init__(self, nameGeneratorFile, name):
        self.name = name
        self.wordGenerators = []
        self.adding = 0
        firstWord = True
        newWordGenerator = WordGenerator()
        for line in nameGeneratorFile:
            line = line.strip('\n')
            if line == 'word':
                if firstWord == True:
                    firstWord = False
                else:
                    self.wordGenerators.append(newWordGenerator)
                newWordGenerator = WordGenerator()
            elif line == 'prefix':
                adding = 0
            elif line == 'syllable':
                adding = 1
            elif line == 'suffix':
                adding = 2
            else:
                if adding == 0:
                    newWordGenerator.prefixes.append(line)
                elif adding == 1:
                    newWordGenerator.syllables.append(line)
                elif adding == 2:
                    newWordGenerator.suffixes.append(line)
        self.wordGenerators.append(newWordGenerator)
 
    def getNumWords(self):
        return len(self.wordGenerators)
 
    def getWord(self, wordNumber): #wordNumber is 0 based!
        return self.wordGenerators[wordNumber].getWord()
 
    def getName(self):
        name = ''
        for i in range(0, len(self.wordGenerators)):
            if i == 0:
                name = self.getWord(i)
            else:
                name = name + self.getWord(i)
            if i <= len(self.wordGenerators) - 1:
                name = name + ' '
        return name

Finally – one more file/class, the nameGeneratorManager encapsulates the loading and storing of the name generators in a dictionary:

from nameGenerator import *
nameGenerators = {}
 
class NameGeneratorManager:
    def __init__(self):
        pass
 
    def load(self):
        path = os.path.join("../data/default/nameGenerators/")
        fileNameList = map(lambda x:x[len(path):-4],
                           glob.glob(os.path.join(path,"*.txt")))
 
        for name in fileNameList:
            fullName = os.path.abspath(path)
            fullName = os.path.join(fullName, name+'.txt')
 
            nameGeneratorFile = open(fullName)
            newNameGenerator = NameGenerator(nameGeneratorFile, name)
            nameGeneratorFile.close()
            nameGenerators[newNameGenerator.name] = newNameGenerator
This entry was posted in Uncategorized and tagged , . Bookmark the permalink.

One Response to Data Driven Random Name Generation In Python

  1. Xe Chantaka says:

    The more you talk about X-Com, the more I love you.

    I’m definitely going to fire up this alpha now.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

*