Also in preparation for my 7-day roguelike I
rewrote the RingWorks fantasy name generator
and this one is also the most mature by far.
Try it out by playing with the demo (GitHub).
The first implementation was written in Perl. It worked by
interpreting the template string each time a name was to be generated.
This was incredibly slow, partly because of the needless re-parsing,
but mostly because the parser library I used had really poor
performance. It’s literally millions of times slower than this new
The second implementation I did in Emacs Lisp. I didn’t
actually write a parser. Instead, an s-expression is walked and
interpreted for each name generation. Much faster, but I missed having
the template syntax.
five primitive name generator prototypes — including strings
themselves, because anything with a toString() method can be a name
generator — which the compiler composes into a composite generator
following the template. The neatest part is that it’s an optimizing
compiler, using the smallest composition of generators possible. If a
template can only emit one possible pattern, the compiler will try to
return a string of exactly the one possible output.
typeof NameGen.compile('(foo) (bar)');
// => "string"
Here’s the example usage I have in the documentation. On my junk
laptop it can generate a million names for this template in just under
var generator = NameGen.compile("sV'i");
generator.toString(); // => "entheu'loaf"
generator.toString(); // => "honi'munch"
However, in this case there aren’t actually that many possible
outputs. How do I know? You can ask the generator about what it can
generate. Generators know quite a bit about themselves!
// => 118910
var foobar = NameGen.compile('(foo|bar)');
// => 2
foobar.enumerate(); // List all possible outputs.
// => ["foo", "bar"]
After some experience using it in Disc RL I found that it would be
really useful to be mark parts of the output to the capitalized.
Without this, capitalization is awkwardly separate metadata. So I
extended the original syntax to do this. Prefix anything with an
exclamation point and it gets capitalized in the output.
For example, here’s a template I find amusing. There are 5,113,130
possible output names.
Here are some of the interesting output names.
Quisey the Dork
Cunda the Snark
Strisia the Numb
Pustie the Dolt
Blhatau the Clown
Mostly as an exercise, I also added tilde syntax, which reverses the
component that follows it. So
~(foobar) will always emit
don’t think this is particularly useful but having it opens the door
for other similar syntax extensions.
using this library for name generation!