Random Item Names – Roguelike Design part 1 1


In yesterday’s post, I introduced a simple random weapon generator that I designed and published at https://noroguesallowed.com. In that post, I talked about why I designed it… now I’m going to talk about how. There’s a few things I want you to know first:

First: I’m a PHP developer. All the code I’m going to share is for PHP, but I try my best to write code that is highly portable and easy to understand. I’m a procedural programmer at heart. Yes, I sometimes use objects. I like functional constructs for some things. I often mix it all together in weird ways, but I’ll try to make it as clear as possible. You might need to look up some replacement functions for your language of choice.

Second: I am re-inventing the wheel. I make websites and web apps for a living. I am not a game programmer. I’ve never studied game design programming. I’ve not researched libraries or frameworks for this. I decided to try and find “my way” and I am in no way intending to suggest that “my way” is The Right Way™.

Disclaimer: All code shared here is my own and is provided with no guarantees that it will work. I assume no responsibility for damages incurred should you use my code in your projects. Also, feel free to use it however you see fit.

Naming

The first thing I wanted to figure out when I started this project was how to generate random names. That’s the cool part, right? You don’t want to just find a dagger… you want to find a Shocking Steel Dagger of Immense Glory +2!

Before starting, I looked at some of my favorite RPGs for inspiration. I found that weapons might have the components mentioned above. I could have settled on generating weapon names with all these components guaranteed, but I decided that I wanted something more… refined.

I want to use this code in a future game engine, so I wanted to design my weapons based on a few probabilities. How many of my weapons will have an element? How many a prefix? If I generate 100 weapons, how many of them will just be a plain weapon with none of these attributes? After about two seconds of pondering, I came up with these completely arbitrary percentages:

  • Element 5% – only a small fraction have an element from one of three different elemental types. More on that later.
  • Prefix 25% – I want a good many to have something like Steel or Rusted
  • Weapon 100% – no blank names
  • Adjective ?? – this is dependent on whether or not we first have an abstract noun. I don’t want a Hammer of Monumental
  • Abstract 35% – a good number of weapons will be “of” something.
  • Bonus .2-10% – there are bonuses from +1-+5 and the chance of receiving them goes down s the number grows.

With a little bit of research, I came up with a small list of words for each of these categories and packed them into a few arrays.

$element = array('flaming', 'freezing', 'shocking');
$weapon = array('sword', 'axe', 'mace', 'glaive', 'dagger', 'bow', 'halberd', 'spear', 'hammer', 'flail', 'greatsword', 'staff');
$prefix = array('steel', 'iron', 'silver', 'gold', 'vorpal', 'alabaster', 'rusted', 'inferiror', 'superior', 'glowing', 'shining', 'gilded', 'intelligent', 'ethereal', 'demonic', 'divine', 'enchanted', 'pristine', 'weathered', 'etched', 'chipped');
$attributive_adjective = array('blasphemous', 'greater', 'lesser', 'holy', 'unholy', 'captive', 'spurious', 'catastrophic', 'fatal', 'glorious', 'special', 'deformed', 'sharp', 'eternal', 'barbaric');
$abstract_noun = array('brilliance', 'brutality', 'coldness', 'determination', 'evil', 'goodness', 'hope', 'tolerance', 'anger', 'clarity', 'power', 'pride', 'strength', 'awe', 'chaos', 'death', 'life', 'dexterity', 'energy', 'faith', 'justice', 'knowledge', 'luck', 'mercy', 'omen', 'shock', 'skill', 'speed', 'truth', 'chaos');

At this point, all I’m trying to do is dynamically build some weapon names based on the percentages listed above. For this, I’m going to use the PHP build-in rand() function. I’m not worried about what these attributes do at this point, I just want the script to run and output a name. I’m just going to do some string concatenation starting at the element

  $weapon_name = '';

  // Element
  if (rand(1, 100) <= 5) {
      $weapon_name .= $element[rand(0, (count($element) - 1))];
      $weapon_name .= ' ';
  }
}

Top to bottom, I initialize an empty string called $weapon_name. Next, I generate a random number between 1-100 and check to see if that number falls inside my 5% range. If it does, great! We pick a random element from our $element array. We can do this dynamically using the count($element) statement. This way, if we add or subtract items from our $element list, our code will adapt to the new number. The thing to remember is that count() starts at 1 while your array index starts at 0. So, we generate a random number between 0 and count() – 1.

If we add an element, I add a space after the name. I know there’s going to be a weapon name and there needs to be a space between. You could add a space before the weapon name, but I generally like to add my spaces after. I also like to use a new concatenation operation for that just for clarity when reading the code. You’ll find that my code often looks bloated because I write for clarity. If that bothers you, feel free to never tell me. 😀

The rest of the generator is more of the same with varying percentages for each if() statement.

////////////////////////////////////////////////////////////////////////////////
// fuction createWeapon()
////////////////////////////////////////////////////////////////////////////////
// Creates a fantasy weapon name
// takes no arguments, returns string
////////////////////////////////////////////////////////////////////////////////
function createWeapon() {
  global $element, $weapon, $prefix, $attributive_adjective, $abstract_noun;

  $weapon_name = '';

  // Element
  if (rand(1, 100) <= 5) {
    $weapon_name .= $element[rand(0, (count($element) - 1))];
    $weapon_name .= ' ';
  }

  // prefix
  if (rand(1, 100) <= 25) {
    $weapon_name .= $prefix[rand(0, (count($prefix) - 1))];
    $weapon_name .= ' ';
  }

  // weapon
  $weapon_name .= $weapon[rand(0, (count($weapon) - 1))];

  // attribute and possibly adjective
  if (rand(1, 100) <= 35) {
    $weapon_name .= ' of';
    // only some get an adjective
    if (rand(1, 100) <= 40) {
      $weapon_name .= ' ';
      $weapon_name .= $attributive_adjective[rand(0, (count($attributive_adjective) - 1))];
    }
    $weapon_name .= ' ';
    $weapon_name .= $abstract_noun[rand(0, (count($abstract_noun) - 1))];
  }

  // power modifier
  if (rand(1, 100) <= 10) {
    $weapon_name .= ' ';
    $modifier = rand(1, 100);

    switch (true) {
      case ($modifier <= 5):
        $weapon_name .= '+5';
        break;

      case ($modifier <= 15):
        $weapon_name .= '+4';
        break;

      case ($modifier <= 27):
        $weapon_name .= '+3';
        break;

      case ($modifier <= 40):
        $weapon_name .= '+2';
        break;

      default:
      $weapon_name .= '+1';
    }
  }
  return ucwords($weapon_name);
}

As you can see, I step through each of the elements in order and determine if we are going to have that element in our final name. The Adjective and Power Modifier sections are slightly different.

For the adjective, I first need to determine if we are going to get an abstract noun. I check against the previously determined 35% first. If we succeed at getting an abstract noun, I ad “of” to the name and then check if we are going to get an adjective. Of the 35% that receive an abstract noun, 40% of those receive an adjective (that’s about 14% of all total weapons). Also, you may notice that I do not add a space after the adjective/noun.

I check the power modifier in two steps. First I determine if this is one of the 10% that will receive any modifier at all. Then I generate a new random number to check what level that modifier will be. The +5 modifier is 5%of 10% which is .2% of all weapons generated. I use a switch statement here because… well, that’s the solution I came up with. I’m sure there’s a few different ways to do this, and there might even be a fancy math-only way, but this reads clearly enough. I generally don’t use a lot of switch statements in my code.

Finally, I use ucwords() to format the name in title uppercase. This is not syntactically correct because the PHP implementation doesn’t take into account words that are not capitalized like the “of” in our weapon names. I’ll work through that in a later post as I start to flesh out the rest of the weapons attributes. For now, a simple for loop can run and will generate us a list of basic weapon names.

for ($i = 0; $i <= 10; $i++ ){
  echo createWeapon();
  echo '<br />';
}
Staff
Spear
Shining Mace
Silver Dagger
Etched Flail +4
Inferiror Bow Of Catastrophic Mercy
Spear Of Holy Clarity +1
Mace
Divine Flail
Staff Of Pride

What’s next?

I was pretty happy at this point with just the name generation, but I wanted more! I wanted to be able to give each of these random attributes some values that add on to the base weapon values. In the next post, I’ll detail how I set up a mySQL database to handle all the various values, and how the code changed to accommodate the calculations. After values are added, we’ll work on a system to help us generate “weighted” weapons based on character level or dungeon level. Stay tuned!

https://noroguesallowed.com


Leave a comment

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

One thought on “Random Item Names – Roguelike Design part 1