Game Development

Blog 873: A Little Bit of Procgen (All Night Long)

I snuck a little last-minute bonus feature into version 0.05 of Exon: Fragment with no fanfare — the ability to say “Surprise Me!” on the character naming screen. That’s right, I dropped in an exon name generator.

Why did I do this? Partly because it’s hard to think of character names for my test runs and partly… because I have a nefarious plan.

A Little Bit of Procgen (All Night Long)

The titular exons are numerous. You, the player, are merely one of at least hundreds locally, but thousands nationwide and surely millions worldwide. I, a solo game developer, cannot actually implement thousands or millions of unique characters to provide background colour when you visit waystations that are supposed to be “bustling” with these itinerant adventurers.

Can you see where this is going?

Yes, I’m working on the procedural generation of exons to wander through some areas. They come into existence at map edges, follow patrol routes to the shops, wander for a while, and then leave. This might seem like a distraction, but, well, it’s part of the feature creep that’s preventing me from unlocking the Friendly Arm Waystation in the demo (and the Rest of the Prologue that follows). So humour me or you won’t get any more content! Ha!

The Friendly Arm Waystation is now also home to a marble shrine. They take their veneration of exon “saints” very seriously.

The plan began with the name generator. What’s in a name? Surely an exon as called by any other name would smell as sweet?

My conceit is that exon names are like forum aliases. On becoming an exon, you pick a pseudonym that buffers your life as an adventurer from your life as a normal member of society; but you stick with that pseudonym forever and build up a reputation (and relationships) using it. Sure, some people used their real names when they went onto forums back in the day, but they were the crazy ones — most of us picked something entirely made up just because it sounded cool, like, say, “Rao Dao Zao“.

The phase one name generator came togther very quickly, so it made it into Fragment v0.05. This is a bog-standard Markov Chain system into which I’ve plugged a huge library of character names from my favourite games and films and so on, boiling them down into a statistical mush of “given two letters, what letter can come next?” I dug up some of my old code from a previous exploration of Markov Chains and… uh… obliterated it to make it fit the Unity ecosystem.

Even with a corpus as big as I currently have, repeats do crop up regularly enough to be a concern, so it’s not over yet. I’m currently adding extra rules for prefixes, suffixes and mutations (such as leetspeak), extra generators (e.g. take two cool/edgy words and ram them together) and even chaining several generators together, to ensure that there’s a wide variety of naming conventions.

I was going to add a pub with a “rumours” system, until I realised that these transient exons are an excellent place to drop random hints and bits of flavour text. Gives you a reason to talk to them at all!

It occurred to me that this exon generator should be somewhat deterministic — it should be possible to meet the same exon again, and so I must be able to recreate any one (give or take them having had a respray or bought a new sword in the meantime). Unity actually has two random number generators whose seeds can be reset for this purpose… but neither of them is quite right.

Unity’s own random number generator is static, shared by the entire universe, so it’s great for explosion effects and other visual stuff where repeatability is not a concern — just fire and forget me a number. However, the fact that it’s shared by all the world means that resetting its seed could cause other unrelated things to repeat too. Boo hiss.

The C# standard library’s System.Random generator is not static, but that comes with its own problems. You can only set the seed on a System.Random when you instantiate it, which means, yes, suddenly you’re allocating memory for a new number generator every time you make a new exon. That might be fine when you want something big like an entire level to be deterministic from a seed value, but it’s awfully wasteful for doing lots of smaller things at variable intervals.

So I… I’m so sorry… I implemented my own pseudo-random number generator. Or rather, I took some code snippets off the internet for the “XorShift” algorithm and packed them into a little class of my own. This satisfies my twin needs of being isolated but reusable; a single instance can have its seed reset at runtime without rebuilding the entire thing, while that instance can be insulated from outside interference. I don’t have the faintest idea how or why it works, but that’s what internet code snippets are for, right?

I lack the words to adequately express my feelings about this. The closest I can come up with is “WHAT THE EVER-LIVING FUCK???”

The rest of generating an exon is stuff I’ve done many times before. Pick a unit type. Slap a colour scheme on it. Give it some equipment items.

The mechanics of spawning and disposing of transient exons are maybe slightly more interesting, mainly because of how time passes in the game. Everything is fine if you remain on a particular map for a long period, because the simulation runs naturally — the generated exon will follow their path from the map edge, to the shops, then back to the map edge for disposal.

But the campaign has a clock, a measure of the number of hours and days since you started the game, which is scaled off real time spent in levels but also advanced by large increments during overworld travel (and possibly sleeping, if I add a hotel to the Waystation). What if you leave a level for six hours (of game time) and come back later? Surely some of those transient exons should have moved on by then? As it stands, they will not, because my save/load system is fundamentally designed to restore the state of a map to exactly how you left it (except for environmental conditions).

Actually the answer isn’t that interesting. All I have to do is to tag each generated exon with a campaign time for when it should be gone, and check that when you re-enter the map. If it’s past bed-time, bye bye exon.

And you tell me...

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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