2009-09-11 Elite Names

I’m thinking of a system name generator for my upcoming Traveller UWP generator.

I was trying to write code in Perl, based on code in Python, based on code in C, reverse engineered from assembly code written for the Elite video game random name generator on the BBC.

in Python

in C

I didn’t realize that just a a few posts later somebody had already rewritten it in Perl! 😆

in Perl

But then I started wondering: How the hell did this work? How much of the magic was just a pseudo random number generator? Clearly the algorithm was picking pairs of characters from the digraph string. There was an element controlling the length of the name, and that’s it? I tried it, but the names were less than stellar. Then I realized that the digraph string probably listed pairs that went together well. I should not be picking starting characters at random, I should be picking pairs at random. The result is this:

my $digraphs = "..lexegezacebisousesarmaindire.aeratenberalavetiedorquanteisrion";
my $max = length($digraphs);

sub name {
  my $length = 5 + rand(5); # 4-8
  my $name = '';
  while (length($name) < $length) {
    $name .= substr($digraphs, 2*int(rand($max/2)), 2);
  }
  $name =~ s/\.//g;
  return $name;
}

for my $n (0..100) {
  printf "%3d. %s\n", $n, name();
}

Random names:

1. ertexebeis

2. cetiisar

3. marain

4. atsocezaat

5. biraza

6. tezaordi

7. beenes

8. orxeesle

9. quxeisis

10. errabiat

11. riquatis

12. inisered

13. diraanated

14. orquisbiqu

15. arvevein

16. lebereza

17. gemazaisen

18. inzadius

19. isbixebiti

20. vemama

Sounds good to me! ✌

And by changing the digraph, you can get different sounds, too.

my $digraphs = "fafemalunabararerixevivoine.n.q.pazizozutatetitotu..";

Results in this list:

1. zuravo

2. zobarati

3. zireqti

4. efare

5. votuqbain

6. vomafezo

7. fantaetu

8. xeinra

9. ferati

10. ribabata

I like it! 👌

More variation in name length?

my $length = 4 + rand(7); # 4-8

Anyway… I ended up writing a complete name generator:

This generator will first generate a string of digraphs and then generate a bunch of names based on it. – Name Generator

Name Generator

I use it often. For example, for my character in Chult, I had the following link on my character sheet:

Nzurishu Mvelethiji Fighini Shewashi Ngimvusho Mbokhende Nyofe Gugha Yojami Fothunze Thambi Dhupe Yiyidhu Nguzu Zofegha Womakhi Ndutuzu Nodhaso Nyochu Mvejanza – Swahili phonemes

Swahili phonemes

Easy names for non-player characters!

​#RPG ​#Software ​#Generator ​#Traveller ​#Elite

Comments

(Please contact me if you want to remove your comment.)

Awesome.

Back when I was trying out StackOverflow (I later learned to dislike it), I tackled a similar problem about phonetic passwords. My solution would concatentate words from the dictionary. The more elegant answer that was accepted suggested a well known method using digraphs (maybe even trigraphs).

StackOverflow

phonetic passwords

The digraph is a much better solution, and I think using a string as the data structure as you have done is not only sharp, but its also makes it easier to understand how it works.

– AaronHawley 2009-09-16 22:21 UTC

AaronHawley

---

The thing I really liked about the solution was how it uses the dot to produce shorter than expected words (if you use «..») and how you can generate three-letter syllables (if you use «.»). I thought of Japanese were you have combinations of the consonants k, s, t, n, h, m, b, s, z followed by a, e, i, o, u, ya, yu, yo (but no ye and yi), the vocals themselves, and the letter n by itself. You can represent that using the following:

my $digraphs = "kakekikokusasesisosutatetitotunaneninonuhahehihohu"
  . "mamemimomubabebibobusasesisosuzazezizozuyayuyoa.e.i.o.u.n.";

The only obvious problem is the placement of the single n at the beginning of a word, and the distribution of the syllables used. Not too shabby:

1. misakumeho 1. zukunahimi 2. misekusohi 3. hosato 4. nahokesu 5. titizobuha 6. keeyosuo 7. kimotizi 8. ihosikahi 9. misouisu

Ovious «n» endings, for example:

1. setanheo 34. bayonunyu 42. nhezase 57. hihezenin

– Alex Schroeder 2009-09-16 23:03 UTC

Alex Schroeder

---

All this reminds me of the Dada Engine.

http://dev.null.org/dadaengine/

Which famously functions for the Postmodernism Generator

http://www.elsewhere.org/pomo/

– AaronHawley 2009-09-17 01:30 UTC

AaronHawley

---

Cool. That would be the way for a most awesome name generator. 🙂

– Alex Schroeder 2009-09-17 07:35 UTC

Alex Schroeder

---

I was recently revisiting this code. As it took me a minute to find the python code again, I’m going to keep a copy, here:

# https://cartographersguild.com/showthread.php?t=3571&page=2&p=40167#post40167

ELITE = True

if ELITE:
    seed = [0x5A4A, 0x0248, 0xB753]
else:
    import random
    seed = [random.randint(0, 0xffff), random.randint(0, 0xffff), random.randint(0, 0xffff)]

def tweakseed():
    temp = (seed[0] + seed[1] + seed[2]) % 0x10000
    seed[0] = seed[1]
    seed[1] = seed[2]
    seed[2] = temp

digraphs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion"

def name():
    longnameflag = seed[0] & 0x40
    name = ""
    # print(seed[0], seed[1], seed[2]);
    for n in range(4):
        d = ((seed[2] >> 8) & 0x1f) << 1
        tweakseed()
        if n < 3 or longnameflag:
            name += digraphs[d:d+2]
    return name.replace(".", "").title()

for n in range(12):
    print(name());

This is what you get:

Reimplementing it in Perl without relying on srand and rand such that I could use it for my Capsules for Phoebe extension:

Capsules for Phoebe

# Fingerprints look like this:
# sha256$0ba6ba61da1385890f611439590f2f0758760708d1375859b2184dcd8f855a00
# To get the Elite names, use:
# sha256$5a4a0248b753
# say substr($fingerprint, 7, 12);
# 23114 584 46931

use Modern::Perl;
use List::Util qw(sum);

my $fingerprint = 'sha256$5a4a0248b753';
my @stack = map { hex } substr($fingerprint, 7, 12) =~ /(....)/g;

say ucfirst capsule_name() for (1 .. 12);

sub capsule_name {
  my $digraphs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion";
  my $longname = $stack[0] & 0x40;
  my $name;
  # say "@stack";
  for my $n (1 .. 4) {
    my $d = (($stack[2] >> 8) & 0x1f) << 1;
    push(@stack, sum(@stack) % 0x10000);
    shift(@stack);
    $name .= substr($digraphs, $d, 2)
	if $n <= 3 or $longname;
  }
  $name =~ s/\.//g;
  return $name;
}

I love those self-written random number generators.

– Alex 2021-11-05 15:14 UTC