Author Topic: Name generator  (Read 39176 times)

Offline Tricky

  • BFF
  • ***
  • Posts: 189
  • I like what I code and I code what I like!
    • View Profile
Name generator
« on: September 23, 2008, 03:28:14 pm »
The other day I decided to code a sefun that created a name that could be pronounced more easily by my self. This is the result.

To use, place the file in the sefun directory and #include it in /secure/sefun/sefun.c (DS lib), update /secure/sefun/sefun. Now it is ready to use.

generate_name(pair, num, ind);

The parameters are all optional.

 * pair - Which of the letter-pair sets to use. (0 - 4)
 * num - Which of the 8 sets of generated names to use. (1 - 8)
 * ind - Which name to use. (0 - 255)

The function returns a capitalized name.

Code: [Select]
/* /secure/sefun/names.c
 *
 * A general purpose name generator based on digraphs/letter-pairs.
 *
 * The original concept comes from the space trading game Elite.
 * Ian Bell (one of the original coders of Elite) converted the 6502
 * assembly source code into a C version (minus graphics).
 *
 * This is an LPC conversion that just uses the name generation code.
 *
 * The original source can be found here...
 *   http://www.iancgbell.clara.net/elite/text/index.htm
 *
 * --------------------------------------------------------------------
 * Unless I specify in file headers, all my stuff I release will be
 * Public Domain. Do as you want with it or not. The choice is yours.
 *
 * If I want to be paid for code, then I will pimp myself to a company.
 *
 * Tricky
 */

#define RTH_MAX_NAMES 256

private static string *rth_pairs_arr = ({
/* Planets from the original Elite */
  "..lexegezacebiso" +
  "usesarmaindirea." +
  "eratenberalaveti" +
  "edorquanteisrion",
/* Lorem ipsum */
  "..qupeaudidoliut" +
  "viadaedupasotoa." +
  "loaregelpufridhe" +
  "geimmeneninopier",
/* War and Peace */
  "..hethineranrena" +
  "ouonedneathatoa." +
  "isenitasteesaror" +
  "lenistverineseli",
/* Front page of Boing Boing (including HTML) */
  "..indiennatehaiv" +
  "bonereanasthoia." +
  "celaeterpariryte" +
  "atlehesetaarcoes",
/* The Little Prince (Chapters 1-5, English version) */
  "..thheanerinhaat" +
  "reouisittoonvea." +
  "histedleennamees" +
  "nenoofearoseorar",
});

private static string rth_pairs;

private static mapping rth_seed = ([
  "w0": 0,
  "w1": 0,
  "w2": 0,
]);

private static int rth_rotatel(int x)
{
    x = (x & 255) * 2;
    if(x > 255) x -= 255;
    return x;
}

private static int rth_twist(int x)
{
    return (rth_rotatel(x >> 8) << 8) + rth_rotatel(x & 255);
}

private static void rth_next()
{
    rth_seed["w0"] = rth_twist(rth_seed["w0"]);
    rth_seed["w1"] = rth_twist(rth_seed["w1"]);
    rth_seed["w2"] = rth_twist(rth_seed["w2"]);
}

private static void rth_tweakseed()
{
    int tmp;

    tmp = rth_seed["w0"] + rth_seed["w1"] + rth_seed["w2"];
    tmp &= 65535;

    rth_seed["w0"] = rth_seed["w1"];
    rth_seed["w1"] = rth_seed["w2"];
    rth_seed["w2"] = tmp;
}

private static string rth_makename()
{
    string name;
    int pair1, pair2, pair3, pair4;
    int longname = rth_seed["w0"] & 64;

    /* Always 4 iterations of random number */
    pair1 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair2 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair3 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair4 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();

    name  = sprintf("%c", rth_pairs[pair1]);
    name += sprintf("%c", rth_pairs[pair1 + 1]);
    name += sprintf("%c", rth_pairs[pair2]);
    name += sprintf("%c", rth_pairs[pair2 + 1]);
    name += sprintf("%c", rth_pairs[pair3]);
    name += sprintf("%c", rth_pairs[pair3 + 1]);

    /* bit 6 of ORIGINAL w0 flags a four-pair name */
    if (longname)
    {
        name += sprintf("%c", rth_pairs[pair4]);
        name += sprintf("%c", rth_pairs[pair4 + 1]);
    }

    /* Remove any '.' in the name and capitalize the result */
    name = capitalize(replace_string(name, ".", ""));

    return name;
}

varargs string generate_name(int pair, int num, int ind)
{
    string array names = allocate(RTH_MAX_NAMES);

    if(undefinedp(pair) || !intp(pair)) pair = random(sizeof(rth_pairs_arr));
    if(pair < 0 || pair >= sizeof(rth_pairs_arr)) pair = 0;

    rth_pairs = rth_pairs_arr[pair];

    if(undefinedp(num) || !intp(num)) num = random(8) + 1;
    if(num < 1 || num > 8) num = 1;

    rth_seed["w0"] = 0x5a4a;
    rth_seed["w1"] = 0x0248;
    rth_seed["w2"] = 0xb753;

    for (int i = 1 ; i < num ; ++i) rth_next();

    for (int i = 0 ; i < RTH_MAX_NAMES ; ++i)
        names[i] = rth_makename();

    if (undefinedp(ind) || !intp(ind)) ind = random(RTH_MAX_NAMES);
    if (ind < 0 || ind >= RTH_MAX_NAMES) ind = 0;

    return names[ind];
}

Tricky

Offline quixadhal

  • BFF
  • ***
  • Posts: 642
    • View Profile
    • WileyMUD
Re: Name generator
« Reply #1 on: September 24, 2008, 11:10:09 am »
Wow, it's pretty cool that I saw the name iancgbell in the URL before I looked upwards to see the comments, and said "Hey, that's the guy who did Elite!"

While I don't know if he ever plans to do the long-idle Elite 4, the spiritual successor of Elite is about to release their next game, X3: Terran Conflict.

Elite was phenomenal becuase almost all the content was procedurally generated, making it possible to have a huge galaxy with 3D dogfights on the Commodore 64.  Spore is the first commercial game to go down that route in a long time, and I hope to see more.

Good job remembering/finding this, and then doing the work to port it over! :)

Offline Tricky

  • BFF
  • ***
  • Posts: 189
  • I like what I code and I code what I like!
    • View Profile
Re: Name generator
« Reply #2 on: September 24, 2008, 04:26:00 pm »
 ;D NP

In some interviews I've read they could have had over 2 billion galaxies generated on the fly. However, the games company reeled them back into the real world and they cut it down to the 8 we know about.

As for Elite 4, current rumour is that work will begin on it once X3 is launched and selling well for XMas. (Heard it all before ::) )

Tricky

Offline chaos

  • BFF
  • ***
  • Posts: 291
  • Job, school, social life, sleep. Pick 2.5.
    • View Profile
    • Lost Souls
Re: Name generator
« Reply #3 on: September 25, 2008, 03:36:59 pm »
LDMud port:

Code: [Select]
/* /secure/sefun/names.c
 *
 * A general purpose name generator based on digraphs/letter-pairs.
 *
 * The original concept comes from the space trading game Elite.
 * Ian Bell (one of the original coders of Elite) converted the 6502
 * assembly source code into a C version (minus graphics).
 *
 * This is an LPC conversion that just uses the name generation code.
 *
 * The original source can be found here...
 *   http://www.iancgbell.clara.net/elite/text/index.htm
 *
 * --------------------------------------------------------------------
 * Unless I specify in file headers, all my stuff I release will be
 * Public Domain. Do as you want with it or not. The choice is yours.
 *
 * If I want to be paid for code, then I will pimp myself to a company.
 *
 * Tricky
 */

// Ported to LDMud by Chaos of Lost Souls.  Changes are also public
// domain.

#define RTH_MAX_NAMES 256

private static string *rth_pairs_arr = ({
/* Planets from the original Elite */
  "..lexegezacebiso" +
  "usesarmaindirea." +
  "eratenberalaveti" +
  "edorquanteisrion",
/* Lorem ipsum */
  "..qupeaudidoliut" +
  "viadaedupasotoa." +
  "loaregelpufridhe" +
  "geimmeneninopier",
/* War and Peace */
  "..hethineranrena" +
  "ouonedneathatoa." +
  "isenitasteesaror" +
  "lenistverineseli",
/* Front page of Boing Boing (including HTML) */
  "..indiennatehaiv" +
  "bonereanasthoia." +
  "celaeterpariryte" +
  "atlehesetaarcoes",
/* The Little Prince (Chapters 1-5, English version) */
  "..thheanerinhaat" +
  "reouisittoonvea." +
  "histedleennamees" +
  "nenoofearoseorar",
});

private static string rth_pairs;

private static mapping rth_seed;

void create() {
    rth_seed = ([
        "w0"    : 0,
        "w1"    : 0,
        "w2"    : 0,
    ]);
}

private static int rth_rotatel(int x) {
    x = (x & 255) * 2;
    if(x > 255) x -= 255;
    return x;
}

private static int rth_twist(int x) {
    return (rth_rotatel(x >> 8) << 8) + rth_rotatel(x & 255);
}

private static void rth_next() {
    rth_seed["w0"] = rth_twist(rth_seed["w0"]);
    rth_seed["w1"] = rth_twist(rth_seed["w1"]);
    rth_seed["w2"] = rth_twist(rth_seed["w2"]);
}

private static void rth_tweakseed() {
    int tmp = rth_seed["w0"] + rth_seed["w1"] + rth_seed["w2"];
    tmp &= 65535;
    rth_seed["w0"] = rth_seed["w1"];
    rth_seed["w1"] = rth_seed["w2"];
    rth_seed["w2"] = tmp;
}

private static string rth_makename() {
    string name;
    int pair1, pair2, pair3, pair4;
    int longname = rth_seed["w0"] & 64;
    /* Always 4 iterations of random number */
    pair1 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair2 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair3 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair4 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    name  = sprintf("%c", rth_pairs[pair1]);
    name += sprintf("%c", rth_pairs[pair1 + 1]);
    name += sprintf("%c", rth_pairs[pair2]);
    name += sprintf("%c", rth_pairs[pair2 + 1]);
    name += sprintf("%c", rth_pairs[pair3]);
    name += sprintf("%c", rth_pairs[pair3 + 1]);
    /* bit 6 of ORIGINAL w0 flags a four-pair name */
    if(longname) {
        name += sprintf("%c", rth_pairs[pair4]);
        name += sprintf("%c", rth_pairs[pair4 + 1]);
    }
    /* Remove any '.' in the name and capitalize the result */
    name = capitalize(replace(name, ".", ""));
    return name;
}

varargs string generate_name(varargs int array args) {
    int pair = sizeof(args) >= 1 && args[0];
    int num = sizeof(args) >= 2 && args[1];
    int ind = sizeof(args) >= 3 && args[2];
    string array names = allocate(RTH_MAX_NAMES);
    if(!sizeof(args) || !intp(pair))
        pair = random(sizeof(rth_pairs_arr));
    if(pair < 0 || pair >= sizeof(rth_pairs_arr)) pair = 0;
    rth_pairs = rth_pairs_arr[pair];
    if(sizeof(args) < 2 || !intp(num))
        num = random(8) + 1;
    if(num < 1 || num > 8) num = 1;
    rth_seed["w0"] = 0x5a4a;
    rth_seed["w1"] = 0x0248;
    rth_seed["w2"] = 0xb753;
    for(int i = 1 ; i < num ; ++i)
        rth_next();
    for(int i = 0 ; i < RTH_MAX_NAMES ; ++i)
        names[i] = rth_makename();
    if(sizeof(args) < 3 || !intp(ind))
        ind = random(RTH_MAX_NAMES);
    if(ind < 0 || ind >= RTH_MAX_NAMES)
        ind = 0;
    return names[ind];
}

Offline Xzystance

  • Acquaintance
  • *
  • Posts: 29
    • View Profile
Re: Name generator
« Reply #4 on: September 25, 2008, 06:15:47 pm »
so um, i've included it, and updated it....... now how do i use it? :-P

X

Offline chaos

  • BFF
  • ***
  • Posts: 291
  • Job, school, social life, sleep. Pick 2.5.
    • View Profile
    • Lost Souls
Re: Name generator
« Reply #5 on: September 25, 2008, 06:18:23 pm »
You call generate_name() in it.

Offline Xzystance

  • Acquaintance
  • *
  • Posts: 29
    • View Profile
Re: Name generator
« Reply #6 on: September 25, 2008, 07:14:09 pm »
Ok, i'm feelin kinda noobish, could you give an example of usage? :-P

Offline Tricky

  • BFF
  • ***
  • Posts: 189
  • I like what I code and I code what I like!
    • View Profile
Re: Name generator
« Reply #7 on: September 25, 2008, 07:44:27 pm »
Ok, i'm feelin kinda noobish, could you give an example of usage? :-P

I currently use it in the file /secure/obj/robot.c

Instead of...

Code: [Select]
    if(!name) name = alpha_crypt(random(10)+2);

I have...

Code: [Select]
    if(!name) name = generate_name(2);

This gives me a random name from the whole of the War and Peace set. (8 banks of 256 names)

The following will show a set of names familiar to all the oldbies here...

Code: [Select]
write(generate_name(0, 1, 7) + "\n");
write(generate_name(0, 1, 129) + "\n");
write(generate_name(0, 1, 147) + "\n");

The 1st arg is the pair set to use, 0 is Elite names, 1 is Lorem ipsum (made up Latin script), 2 is War and Peace, 3 is Boing Boing front page, 4 is The Little Prince (Chapters 1-5, English version).

The 2nd arg is the name space to use, in the range of 1 to 8.

The 3rd arg is a specific name (0 to 255).

All the arguments are optional so you can call it like this, generate_name(), which would return a random name from a random name space from a random pair set. generate_name(0, 1) would return a random name from the 1st galaxy of the Elite space trading game.

I hope that gave some clue as to how to call it.

Tricky

Offline Xzystance

  • Acquaintance
  • *
  • Posts: 29
    • View Profile
Re: Name generator
« Reply #8 on: September 25, 2008, 08:00:19 pm »
Yeah, thanks :)

Offline daelaskai

  • BFF
  • ***
  • Posts: 174
    • View Profile
Re: Name generator
« Reply #9 on: September 26, 2008, 11:39:03 pm »
I like the name generator.  Anyone know how to add your own custom name possibilities?
For instance, I'd like to use the name generator to make a bunch of Elven, Dwarven or
Draconic names.  How does someone create the:

Code: [Select]
  "..hethineranrena" +
  "ouonedneathatoa." +
  "isenitasteesaror" +
  "lenistverineseli",

The names need to make sense for what it is being used for.  Any suggestions?

Daelas

Offline chaos

  • BFF
  • ***
  • Posts: 291
  • Job, school, social life, sleep. Pick 2.5.
    • View Profile
    • Lost Souls
Re: Name generator
« Reply #10 on: September 26, 2008, 11:54:17 pm »
It's a lot easier to get 'elfy', 'dwarfy' etc. style names, and see what you're doing, with a simple system where you have a list of 1st, 2nd, and 3rd name 'chunks', and randomly pick one from each column.  The Elite generator is neat, but it's not really the best system for an LPmud, largely because much of what it's doing is to work around constraints that C has and LPC doesn't.

Offline shadyman

  • Friend
  • **
  • Posts: 50
    • View Profile
Re: Name generator
« Reply #11 on: November 24, 2008, 11:16:32 am »
Woo! That's hot. Thanks for sharing!

Offline wick

  • Acquaintance
  • *
  • Posts: 1
    • View Profile
Re: Name generator
« Reply #12 on: August 13, 2009, 12:18:36 am »
This is custom lib so it may not work with any of yours, but this is a neat toy I've used
Code: [Select]
#include <defines.h>

#define VOW ({\
  "e", "e", "e", "e", "e", "a", "a", "a", "a", "i", "i", "i", "o", "o", "u", \
  "e", "e", "e", "e", "e", "a", "a", "a", "a", "i", "i", "i", "o", "o", "u", \
  "e", "e", "e", "e", "e", "a", "a", "a", "a", "i", "i", "i", "o", "o", "u", \
  "e", "e", "e", "e", "e", "a", "a", "a", "a", "i", "i", "i", "o", "o", "u", \
  "y", "ie", "aa", "oo", "ee", "ea", "ia", "io", "ou", "ou", \
})

#define SVOW ({ \
  "e", "e", "e", "e", "e", "a", "a", "a", "a", "i", "i", "i", "o", "o", "u", \
})

#define EVOW ({ \
  "e", "e", "e", "e", "e", "a", "a", "a", "a", "i", "i", "i", "y", "y", "o", \
})

#define CON ({\
  "b", "bl", "br", "c", "ch", "ck", "cl", "cr", "d", "dl", "dr", "f", "fl", \
  "fr", "g", "h", "j", "k", "kl", "kr", "l", "m", "n", "p", "pl", "pr", "ps", \
  "qu", "r", "rn", "rt", "rth", "s", "sch", "scr", "sh", "shr", "sk", "sm", \
  "sn", "sp", "spr", "st", "str", "sw", "t", "th", "tr", "ts", "v", "vr", \
  "w", "wr", "x", "z", "zl", "zr", \
})

#define SCON ({ \
  "b", "bl", "br", "c", "ch", "cl", "cr", "d", "dr", "f", "fl", "fr", "g", \
  "h", "j", "k", "kr", "l", "m", "n", "p", "pl", "pr", "qu", "r", "s", "scr", \
  "sh", "shr", "sk", "sm", "sn", "sp", "spr", "st", "str", "sw", "t", "th", \
  "tr", "v", "w", "x", "z", \
})

#define ECON ({ \
  "b", "ch", "ck", "d", "f", "g", "l", "m", "n", "ng", "p", "ps", "r", \
  "rn", "rt", "rth", "s", "sch", "sh", "st", "t", "th", "ts", "w", "z", \
})

#define RVOW VOW[random(sizeof(VOW))]
#define RSVOW SVOW[random(sizeof(SVOW))]
#define REVOW EVOW[random(sizeof(EVOW))]
#define RCON CON[random(sizeof(CON))]
#define RSCON SCON[random(sizeof(SCON))]
#define RECON ECON[random(sizeof(ECON))]

inherit COMMAND;

int main(string arg) {
  string name;
  int num;

  sscanf(arg, "%d", num);
  if (!num)
    num = 1 + random(3);
  if (num < 1)
    return notify_fail("Less than 1 syllable... aborting.\n");
  if (num > 10)
    return notify_fail("Too many syllables... aborting.\n");

  name = (random(5) ? RSCON+RVOW : RSVOW);
  if (num-- > 0) {
    while (num--) {
      name += RCON;
      name += RVOW;
    }
  }
  if (random(5))
    name += RECON;
  else
    name += RCON + REVOW;

  printf("%s\n", capitalize(name));

  return 1;
}