Why yes, NPCs do grow on trees...
by Ted Southard · 01/12/2009 (12:25 pm) · 25 comments
Just a quick update on some procedural content stuff I'm working on.
I wanted a change of pace from going fisticuffs with the engine's swimming functions (the density and buoyancy is driving me absolutely mad), so I figured that I would take a shot at the NPC generator for the game- just as a little proof-of-concept. I figured that it would be a little struggle to get things together, and probably a bear to manage for the in-game version...
Less than 8 man-hours of scripting later, I can generate the following output (it's text because it's describing NPC stats- this is not about character generation or anything graphical):
Nifty, and the best part is that the only part of this that isn't game-ready at all is the "Backstory" part. So the name, vitals, skills (even though I didn't dump them- I couldn't bear doing a billion echo()'s, lol, but there are skill packages that are profession-dependent), and KB Levels are all generated so that they can be fed into the game's DB to generate an NPC. Though the KB Level part, which is used to assign the conversation contexts available to the NPC for the conversation system, is half-done, because I'm trying to decide how I want to determine the knowledge depth of each context (by age, faction, region, most likely some combination, etc). The name generator is production ready for the "Charkritian" faction, with 69706 unique male and 61663 unique female names, excluding the use of middle names (which, if made optional, would boost those numbers up to something like 12 million for male and female each).
NOTE: I just noticed the NPC's Max Physical Endurance amount... Scary, heh ;)
There's a few more things I want to do with this, such as generation of loot, generation of known abilities (probably will do that dependent on skill levels/faction/profession), and of course the DB serialization function- which is basically just an NPC loading function done in reverse. And the hardest part: Fleshing out the "Backstory" part and pushing that into the DB as a "self-context" for the conversation system. It's not high-priority compared with the rest, but I think it would add a lot of character to the world if generated NPCs can be asked about their life and times before the point of time where the gameworld starts. It does become more important though when you get into mission/situation generation and the NPCs need to have motivations besides just being "aggro'ed" by the player.
All in all, I'm very pleasantly surprised by this little experiment, so I'm definitely going to try to drive the rest of these features home and then generalize the namespace for use by the game in a more automated fashion for the mission generation system.
Also, I think that this procedural content generation stuff is a good deal easier than people think it is. You don't need to know fractals or anything wild to do something like this. Just a lot of randInRange() calls and table lookups. As a matter of fact, Anarchy Online does a good deal of procedural content generation now, and within gameplay-contexts that make it very easy for players to accept. This is the direction that MMO content will be headed in very soon (or already has, in the case of an indie MMO or two I know of floating around this community other than my own), as user populations increase and it becomes increasingly expensive to write prose for fed-ex quests.
Not that human-writing doesn't have its place- it most definitely does. But as your requirements for content go up, so does the costs associated with hiring more and more writers. And those writers, however good they may be, should not be aimed at the million small quests you want players to experience 99% of the time. It's probably better, from both a quality and cost perspective, in the long-run to get these writers to create discrete "chunks" of story and dialog that are generic enough to be mixed and matched into generated story-arcs and conversation "contexts" which can be reused. And in this way, you get to generate your missions, and do so with better quality writing since you're not making your writer write fifty variations of the same quest him- or herself.
I know there's resistance to the idea, and like all things, it's not a one-size-fits-all solution, but when done right and in the proper contexts, I do believe that it can really help fill up a world with higher-quality content.
I wanted a change of pace from going fisticuffs with the engine's swimming functions (the density and buoyancy is driving me absolutely mad), so I figured that I would take a shot at the NPC generator for the game- just as a little proof-of-concept. I figured that it would be a little struggle to get things together, and probably a bear to manage for the in-game version...
Less than 8 man-hours of scripting later, I can generate the following output (it's text because it's describing NPC stats- this is not about character generation or anything graphical):
Basics: Hiraka Ilar is a male of 44 years of Charkritian descent from Stellar City who is a Soldier. Personality: Hiraka Ilar has: a below average sense of dominance, a average level of sensitivity, a below average level of altruism, a above average level of patience, a above average level of stability, a low level of trust, a low sense of confidence, a below average sense of extroversion, a above average level of openness, and a high level of discipline. Backstory: Hiraka Ilar was not sickened by the Pandemic. Hiraka Ilar's mother died from the Pandemic. Hiraka Ilar's father is dead. Hiraka Ilar is an only child. This character's upbringing was pleasant, aside from all the problems. Hiraka Ilar is not married. Hiraka Ilar has no children. Vitals: Hiraka Ilar's health is 884 Physical Endurance is 666 Mental Endurance is 668 Strength is 4 Agility is 5 Intelligence is 6 Charm is 6 Skills: KB Levels: 1 3 5 12
Nifty, and the best part is that the only part of this that isn't game-ready at all is the "Backstory" part. So the name, vitals, skills (even though I didn't dump them- I couldn't bear doing a billion echo()'s, lol, but there are skill packages that are profession-dependent), and KB Levels are all generated so that they can be fed into the game's DB to generate an NPC. Though the KB Level part, which is used to assign the conversation contexts available to the NPC for the conversation system, is half-done, because I'm trying to decide how I want to determine the knowledge depth of each context (by age, faction, region, most likely some combination, etc). The name generator is production ready for the "Charkritian" faction, with 69706 unique male and 61663 unique female names, excluding the use of middle names (which, if made optional, would boost those numbers up to something like 12 million for male and female each).
NOTE: I just noticed the NPC's Max Physical Endurance amount... Scary, heh ;)
There's a few more things I want to do with this, such as generation of loot, generation of known abilities (probably will do that dependent on skill levels/faction/profession), and of course the DB serialization function- which is basically just an NPC loading function done in reverse. And the hardest part: Fleshing out the "Backstory" part and pushing that into the DB as a "self-context" for the conversation system. It's not high-priority compared with the rest, but I think it would add a lot of character to the world if generated NPCs can be asked about their life and times before the point of time where the gameworld starts. It does become more important though when you get into mission/situation generation and the NPCs need to have motivations besides just being "aggro'ed" by the player.
All in all, I'm very pleasantly surprised by this little experiment, so I'm definitely going to try to drive the rest of these features home and then generalize the namespace for use by the game in a more automated fashion for the mission generation system.
Also, I think that this procedural content generation stuff is a good deal easier than people think it is. You don't need to know fractals or anything wild to do something like this. Just a lot of randInRange() calls and table lookups. As a matter of fact, Anarchy Online does a good deal of procedural content generation now, and within gameplay-contexts that make it very easy for players to accept. This is the direction that MMO content will be headed in very soon (or already has, in the case of an indie MMO or two I know of floating around this community other than my own), as user populations increase and it becomes increasingly expensive to write prose for fed-ex quests.
Not that human-writing doesn't have its place- it most definitely does. But as your requirements for content go up, so does the costs associated with hiring more and more writers. And those writers, however good they may be, should not be aimed at the million small quests you want players to experience 99% of the time. It's probably better, from both a quality and cost perspective, in the long-run to get these writers to create discrete "chunks" of story and dialog that are generic enough to be mixed and matched into generated story-arcs and conversation "contexts" which can be reused. And in this way, you get to generate your missions, and do so with better quality writing since you're not making your writer write fifty variations of the same quest him- or herself.
I know there's resistance to the idea, and like all things, it's not a one-size-fits-all solution, but when done right and in the proper contexts, I do believe that it can really help fill up a world with higher-quality content.
About the author
#22
01/13/2009 (11:58 am)
That's a lot of time to cover. I sort of cheat that by just not having so much "movement". I'd be very interested in what you come up with :)
#23
The system is still stupidly complex, and i'm trying to decide how I want to simplify things for actual coding.
Basically:
From a root culture, I end up with 4 major cultures and ? minor cultures.
At each time step, the currently selected culture can either move farther away, or come into contact with another culture, or stay physically in place.
Linguistically, this means:
Synthesis: the language takes on an aspect of another culture it is contact with. If no cultures, treat as mutation.
Simplification: the language reduces a complex morpheme to a simpler morpheme. If in the 'going away state' change this to removing a morpheme from the language that is the same as a morpheme in a contacted culture (reducing cultural influences).
Mutation: A random new morpheme is added.
Split: The language splits in two, and one of the two immediately undergoes one of the above.
Of course, this is all rather hideously complex for just generating names. But, you know, who knows. My fear is after all the work, it ends up producing gibberish.
Also, I'm thinking that the number of splits in a window of time will need to be limited. To prevent massive tree expansion with no real shifts.
Perhaps I should also allow a rule for culling? Perhaps a culture group died out? Or maybe got merged back into another culture (think the Saxons and Brittons from historical UK).
01/13/2009 (12:08 pm)
My plan is to implement a very simplified linguistic rule system that follows the actual historical mutation of languages. Languages change slowly (relatively) so long periods are needed (in a low-contact society).The system is still stupidly complex, and i'm trying to decide how I want to simplify things for actual coding.
Basically:
From a root culture, I end up with 4 major cultures and ? minor cultures.
At each time step, the currently selected culture can either move farther away, or come into contact with another culture, or stay physically in place.
Linguistically, this means:
Synthesis: the language takes on an aspect of another culture it is contact with. If no cultures, treat as mutation.
Simplification: the language reduces a complex morpheme to a simpler morpheme. If in the 'going away state' change this to removing a morpheme from the language that is the same as a morpheme in a contacted culture (reducing cultural influences).
Mutation: A random new morpheme is added.
Split: The language splits in two, and one of the two immediately undergoes one of the above.
Of course, this is all rather hideously complex for just generating names. But, you know, who knows. My fear is after all the work, it ends up producing gibberish.
Also, I'm thinking that the number of splits in a window of time will need to be limited. To prevent massive tree expansion with no real shifts.
Perhaps I should also allow a rule for culling? Perhaps a culture group died out? Or maybe got merged back into another culture (think the Saxons and Brittons from historical UK).
#24
01/13/2009 (12:21 pm)
That's really nice. A bit too detailed for the goals I'm aiming at, but I think if you want to be able to show names going back in time like that, it's worth it.
#25

There he is, generated and planted into the game- and actually a little closer to production than the others, since he has a bit of the AI stuff in him :) Dumping to a database was very easy, and I just made it the last step in the generation process, so I can spawn him on the fly with all of the above being done, and while I'm sure it eats up some ms in cycles, it's not noticeable by the naked eye (plus you can always make a dedicated server generate content for other servers- it's the smart thing to do anyway, since the game servers have enough to worry about).
Edit: Forgot to mention, if you can't tell which is which, he's the named guy on the left ;)
01/13/2009 (1:50 pm)

There he is, generated and planted into the game- and actually a little closer to production than the others, since he has a bit of the AI stuff in him :) Dumping to a database was very easy, and I just made it the last step in the generation process, so I can spawn him on the fly with all of the above being done, and while I'm sure it eats up some ms in cycles, it's not noticeable by the naked eye (plus you can always make a dedicated server generate content for other servers- it's the smart thing to do anyway, since the game servers have enough to worry about).
Edit: Forgot to mention, if you can't tell which is which, he's the named guy on the left ;)
Torque 3D Owner Martin Young
Of course, first I have to consider the last millenia (or so) of cultural movement so I can have a place to start with my 'root' names.