Random generation makes the heart sing...
Usually the song is some kinda horribly jumbled mess of corrupted lyrics and high pitch screeches, but it sings nonetheless!
If last dev log's theme was all about images, atlases, and goblin bodies, then these next two themes are random generation, random generation, and random generation. If we have time, I might touch on random generation as well.
Let us begin this wonderful code-heavy journey, by getting some good goblin names generated. Once again, I'll be posting the direct copy of my GDScript code, and then writing down pseudo-code step-by-step outlines so you can better understand what's going on as well as translate it into whatever your programming language of choice is.
What's A Goblin Without A Name?
a freaky lookin' frog...
So, we have our ugly subjectively cute goblins generated and ready to go, but they don't have a name! We could just randomly choose a number and then pick that many letters from the alphabet at random, but that doesn't really feel like a name. For example
- xggzyhkb
- niiijsnjht
- sptgnhvwgskb
Those don't feel real, do they? They look like what they are, a bunch of garbled text. We're not making entries in the Library of Babel here, so let's try something else.
How about just pulling a bunch of popular human names, adding them to a large array, and then randomly choosing from there? Sure, but... Let me ask you something. Be honest...
Does this motherfucker look like a "Brian" to you? Nah. Goblins wouldn't follow western English naming styles, I don't even think they speak English. They speak... I dunno, goblinese? Point is, it feels weird to have all these wild & wacky characters only to slap "Bob" under them. Every once & a while that can be funny, but we can do better.
Enter: The Random Name Machine 9000
Sitting at nearly 300 lines long, this marvelous script can generate such great names as:
- Lungeeppee Beltdangler
- Strangling Iddihoozz
- Jumps The Pie
- Bingobbee The Ole Mutt
- ToeGuzzler
- Brutal-Bottom ( ͡° ͜ʖ ͡°)
Now THOSE feel like goblin names! If you're a fan of patterns, you might notice one forming in the names there. Do they look like they follow some sort of... ruleset? Well, that's because they do. Several, in fact.
RULE 1: Curated Lists
Some of these goblin names look more like nicknames and include what could be interpreted as attitude descriptors, hobby events, and appearance tags. In GOBLINFINITE.app, we use 12 lists (or arrays) that lay the fundamental groundwork for our random name generation.
adjectives
- words like runny, chipper, lost, one, rust, always, many
verbs
- words like eat, bash, feast, stab, crash, grab, snack
things
- words like bucket, door, bottom, hole, tunnel, pit, bubble
pluralized_things
- pluralized versions of the
things
list because, unfortunately, it's not as easy as just adding an 's' to the end of the words, for instance: bug -> bugs, but dung -> dung, or elf -> elves
- pluralized versions of the
body_part_names
- words like nose, skin, leg, eye, snout, gut, mouth
pluralized_body_parts
- again, pluralized versions of the
body_part-names
list
- again, pluralized versions of the
prepositions
- words like toward, from, through, into, above, across, against
vowels
- a, ee, i, o, oo, u, because these sound the best in names
consonants
- all the other non-vowel letters
doubles
- good pairings of double letters, like bb, mm, tt, dd, nn, not all double letter pairs sound good, so we curate our own list
combos
- kl, kr, kw, pl, again, not all letter pairings feel right in names, so curation is important
santas_naughty_list
- a very naughty list of words that we check against to make sure our goblins don't get us canceled
With all of our lists populated and ready to draw from, it's on to...
RULE 2: Follow A Formula
In GOBLINFINITE, we have 28 formulas to choose from when picking a name. Maybe a goblin's name should be something like name
+ "the" + plural thing
. Or maybe it should be adjective
+ "-" + plural_thing
. Or body_part
+ _nounify(verb)
. The 28 different formulas are essentially the "recipes" for the names, while the lists act as ingredients. Of course, this is where the recipe metaphor stops, because randomly choosing ingredients from a list might not make for the most appetizing dishes... But for goblin names, it works quite deliciously!
There are a few things I glossed over there, however.
First, how do we generate just a random name
? With nothing else attached? Well, we actually have 2 ways we go about that:
- Variation 1
chunks = 0
.- Start with a random
consonant
orcombo
.chunks += 1
- Add a random
vowel
.chunks += 1
- Randomly choose either a
consonant
,double
, orcombo
.chunks += 1
- GOTO 3.
- Variation 2
chunks = 0
.- Choose a random
vowel
.chunks += 1
- Add a random
consonant
,double
, orcombo
.chunks += 1
- GOTO 3.
The chunks
counter helps stop super long words from generating. The longer the name gets, the more likely it is to end. 1 chunk = 0% chance of ending, 2 chunks = 10%, 3 = 30%, 4 = 50%, 5 = 80%, 6 chunks = 100% chance of ending.
The only time chunks
ending percentage doesn't matter, is when ending on a combo
. Never end on a combo
, even at 100%. Just add a random vowel
and end it there.
Using that formula, we will never go past a name length of 14 characters.
Cool, neat, fun. So what is that _nounify()
function? That's a custom function I wrote to be able to the verb
passed into it, into a noun.
English grammar has a few rules around how nouns should behave, so this function loosely follows them to make verbs into somewhat correct nouns.
if verb.ends_with("e"): return verb + "r"
Pretty straightforward, if the verb ends with the letter "e", then just tack on the letter "r" to the end of the word, and you're good. Dance -> Dancer, Smile -> Smiler, Bake -> Baker.
elif _is_vowel(verb[verb.length()-2]) && not _is_vowel(verb[ver.length()-1]):
return verb + verb[verb.length()-1] + "er"
A little more complex here. _is_vowel()
is just a real quick little function that I can use as a shorthand to check whether the letter being passed into it is a vowel:
Notice how we don't include "y" there? That's because y has to get its shit together and figure out whether or not it wants to be a vowel. No more of this "and sometimes" bullshit. Get your shit straight y, jesus christ...
Anyways, we pass into _is_vowel()
this: verb[verb.length()-2]
. The cool thing about GDScript is that it treats all strings sorta like arrays, so doing some_string[0]
will return you the first letter in that string. Or more clearly, you could do return "hello"[0]
and it will return "h". Neat, right? So verb.length()-2
is the second to last letter, since arrays start at 0.
"hello"["hello".length()]
would give you an error, because "hello".length()
returns 5, but with arrays starting at 0, "hello"[5]
is invalid.
"hello"["hello".length()-1]
would give you "o", because "hello".length()-1
returns 4, and "hello"[4]
is "o".
See how that works? So back to the main code, we are checking to see if the second to last letter is a vowel AND the last letter is not a vowel. If both of those conditions are true, then we should double the last letter (verb + verb[verb.length()-1]
is just duplicating the last letter), and then adding an "er" to the end. Run -> Runner, Jog -> Jogger, Sit -> Sitter.
else: return verb + "er"
If none of the above checks are met, then just simply stick an "er" to the end of the verb. Learn -> Learner, Pretend -> Pretender, Nigg -> -- Uhh... That reminds me, let's move on to that santas_naughty_list
thing...
RULE 3: Let's Try Not To Get Cancelled
Fun fact: English slurs follow English construction guides.
Also fun fact: If you make a random name generator that also follows English construction guides, you will end up generating a surprising amount of slurs.
Doing some tests, I found that for every ~2,000 random names generated, our algorithm would make about 12 slurs. It may only be a 0.6% chance, but I enjoy having calm & relaxing days, not spending my time dealing with freaked-out crazy people yelling at me on Twitter because the silly goblin app put a no-no word on their screen.
Plus, I'm not the only name attached to this. I don't wanna get my boy ROLLINKUNZ canceled. So, we have a simple list of slurs that, upon every completed name generation, we check against. If any word in the freshly generated random name matches any entries in said list, we opt for a little easter-egg replacement.
That's right, if you use GOBLINFINITE.app and ever end up with a goblin named either "ROLLINKUNZ" or "CHIMPCEO", you know 2 things:
- That's a very rare goblin name, less than 1% chance. Cool!
- Your real goblin name was highly offensive... Cool!
And, with those simple rules, you now have PROPER GOBLIN NAMES!
Much better 👍
Lots of code for this one was very GDScript-specific, so the ruleset layout in this post was in effort to make it more like a "guideline" on how to generate your own names. Feel free to play around with the formulas in rule #2, change the list items in rule #1, or be a little rascal and completely remove rule #3.
Next, we're going to cover rolling random stats, and generating random backstories for our little goblin pals.
Until next time, stay safe, keep healthy, and get cozy. See you all soon!
- Chimp CEO 🐒
check out goblinfinite 👉 GOBLINFINITE.APP | ||
---|---|---|
Congratulations @chimp.ceo! You have completed the following achievement on the Hive blockchain and have been rewarded with new badge(s) :
Your next target is to reach 900 upvotes.
You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word
STOP
Check out the last post from @hivebuzz: