nullprogram.com/blog/2009/01/04/
Whether choosing a name for my character in a fantasy game or
populating a world which I pretend to myself that I will one day DM, I
have always gone to the
RinkWorks Fantasy Name Generator. The author of this tool, Samuel
Stoddard, gives some
history on how he came to design and develop it.
It works by using pattern to select sets of letters to put together
into a name. There is a thorough, long
description on the website. Unfortunately, he didn't share his
source code and so we can see how he did it.
Therefore, I used his description to duplicate his generator.
You can grab a copy here with git,
git clone git://github.com/skeeto/fantasyname.git
It includes a command line interface as well as a web interface, which
I am running and linked to at the beginning of this post for you to
use. The code is available under the same license as Perl itself.
I used Perl and the
Parse::RecDescent parser generator. Thanks to this module, it
essentially comes down to about 40 lines of code. The name pattern is
executed, just like a computer program, to generate a name. Here is
the BNF grammar I came up with,
LITERAL ::= /[^|()<>]+/
TEMPLATE ::= /[-svVcBCimMDd']/
literal_set ::= LITERAL | group
template_set ::= TEMPLATE | group
literal_exp ::= literal_set literal_exp | literal_set
template_exp ::= template_set template_exp | template_set
literal_list ::= literal_exp "|" literal_list | literal_exp "|" | literal_exp
template_list ::= template_exp "|" template_list | template_exp "|" | template_exp
group ::= "<" template_list ">" | "(" literal_list ")"
name ::= template_list | group
The program is just that, decorated with some bits of Perl. Since I
came up with it, I have found that it is slightly different than
Mr. Stoddard's generator, in that his allows empty sets anywhere.
Mine only allows them at the end of lists. For example, this is valid
for his generator,
<|B|C>(ikk)
But to work in mine, the empty item must be moved to the end,
<B|C|>(ikk)
This can be adjusted my making the proper changes to the grammar,
which I haven't figured out yet.
Another problem with mine is that Parse::RecDescent is
slooooowwwww. Ridiculously slow. Maybe I designed the grammar
poorly? This is probably the biggest problem. Even simple patterns can
take several seconds to generate names, specifically with deeply
nested patterns. For example, this can take minutes,
<<<<<<<s>>>>>>>
Before you go thinking you are going to tank my server, I have written
the web interface so that it limits the running time of the
generator. If you want to do something fancy, use your own hardware. ;-)
There is also a problem that it will silently drop invalid pattern
characters at the end of the pattern. This has to do with me not quite
understanding how to apply Parse::RecDescent yet.
And this is where I need your help. I have had some trouble coming up
with good patterns. I don't even have a good default, generic fantasy
name pattern. Here are some of mine,
<s|B|Bv|v><V|s|'|V><s|V|C> # default
<i|Cd>D<d|i> # idiot
<V|B><V|vs|Vs> # short
None of which I am very satisfied.
You can design patterns for Nordic names, Gallic names,
Tolkienesque Middle Earth names, orc names, idiot names, dragon names,
dwarf names, elf names, Wheel of Time names, and so on. There is so
much potential available with this tool.
To suggest one to me, e-mail me some patterns, or even better, clone
my git repository and add one to it yourself (then ask me to pull from
you). This way your credit will stay directly attached to it with a
commit.
Good luck!