One way to categorize non-player characters is by whether or not they act separately from the player. Many NPCs are reactive, living only to respond to player actions (assuming they respond at all). They are there to make the setting more real, provide information, or impede the player's progress. They're the cafe patron who doesn't look up from her paper, or the mysterious man in the tweed jacket who talks of destiny and evil forces arrayed against you, or the guard who won't let you into the building until you show her the proper keycard.
Autonomous NPCs are both harder to get right and more rewarding when done well. They don't necessarily wait for the player to do something or stay in one place. They wander around and do their own thing, perhaps making unwanted comments or picking up things you really need.
Autonomous NPCs can be further subdivided based on how they're implemented. Some NPCs are scripted: The NPC does exactly what the author codes. Others are freeform: They have a collection of rules that define their behavior, and the author winds them up and lets them go.
(The above categories are a convenient lie. They're not an either/or choice. They're a continuum, and NPCs may change type as their role changes. The reactive guard may actively search for you if you try to break into the building. Or they may be reactive during play, but active in the story, like how Black in Jigsaw is active offstage but reactive in your presence.)
I'm most interested in autonomous NPCs, since they require more coding and there are so many ways to create them. I'm going to describe some approaches to creating autonomous NPCs and the approaches' advantages and disadvantages. My focus is on NPC actions, like moving around and taking things, rather than conversation, because conversation is really hard and I am really lazy. I'm going to use my game Child's Play as a case study, since those NPCs are all over the map, both literally and figuratively, and since I know their implementation details well.
There's one caveat to keep in mind. This article talks a lot about implementation details, and it's easy to get lost in those details. Players won't care that you created a nifty framework to manage NPCs if it doesn't contribute to their playing experience. Players don't care how you did what you did. They care about what they see. Because of that, my pragmatic advice is to use as simple of an approach as you can get away with. If you can get by with reactive NPCs and some trickery, do it.
Freeform NPCs run on their own. The choice of what a freeform NPC does and when isn't under direct auctorial control. There's no master script telling freeform NPCs what to do and when.
There are a lot of ways to create freeform NPCs. The simplest is to make a list of possible actions and choose one at random. That approach works when you have an NPC who doesn't have to appear intelligent or react to the player. If you're creating a playful dog, you could have it bark, chew on a stick, or run to another room purely at random.
Rather than choosing actions at random, you can define what action or actions should follow the last one, in effect adding memory to the NPC. You can modify the random list of actions based on what the player does, such as throwing a ball to a dog. You can create conditions that determine what set of actions the NPC chooses from, such as the guard who calls out "Who's there?" or heads for players who noisily drop something. You can choose actions based on what the player did in the past, such as a dog who whines and sidles around a player who hit the dog earlier in the game. The TADS 3 Actor State approach is tailor-made for this. If you want, you can use a complex system such as a reactive agent planner, in which freeform NPCs are given goals, ways to achieve that goal, and the ability to choose new sub-goals. For example, consider an NPC whose goal is to find a shotgun to hold off the zombie hordes and who finds the gun cabinet locked would start hunting for the cabinet key. You're only limited by your own willingness to conceive, create, and maintain a complex framework.
Freeform NPCs have a lot of benefits. Because their behavior is often at least partially random, they seem more alive. That's an important consideration if a player is likely to play through one section of your game several times. Freeform NPCs who react to the player's actions seem even more alive.
For the author, freeform NPCs are appealing because, once you have the framework in place, making the NPC do more is easier. That's especially true of frameworks like reactive agent planners, since new goals and behaviors can build on the ones you've already programmed. The base cost of complex NPC frameworks becomes worth it when you have a lot of NPCs and are expecting to add to their behaviors as you work on your game.
The cost of freeform NPCs, both in coding time and complexity, is one of the downsides. If you only have one freeform NPC, do you really want to deal with a framework that can handle multiple NPCs running all over the place and interacting with each other?
Another downside is that freeform NPCs can all feel the same. Having all NPCs perform the same actions may work for a group of faceless tourists, but it's not good for more individual NPCs. To get around that, you can tailor actions to specific NPCs, so that not every NPC does the same thing. Establish an NPC's character by his actions. You can also tailor the reports players see of NPC actions. Minor changes, like replacing "Kate drops the paper cup" with "Kate discards the paper cup," can make a big difference. You can vary a single NPC's action reports each time the NPC performs the action, so that some times Kate discards the paper cup and other times she puts the paper cup down. Greater variation will help mask the underlying mechanical structure. Finally, you can have NPCs react to each other instead of just the player. For instance, in Child's Play some of the babies will follow each other instead of just you.
If your freeform NPCs are randomized, debugging becomes much harder. If your freeform NPCs are randomized and they react to each other, debugging becomes a nightmare. You're guaranteed to have bugs that only show up when NPC 1 interacts with NPC 2 and only when conditions are exactly right, and replicating those conditions will drive you crazy.
Scripted NPCs are far more under your control than freeform NPCs are. You tell scripted NPCs exactly what to do and, usually, when to do it. This is a classic approach in interactive fiction, like having a guard who wanders a fixed route. Many games constrain the player's location and then have NPCs talk either to the player or to another NPC, giving chunks of information through that completely scripted conversation.
The easiest scripted NPC is little more than a list of actions that you run through sequentially. You can add complexity by having different scripts that run depending on what the player has done, or scripts that branch in response to the state of the game world.
The biggest benefit of scripted NPCs is their simplicity, even when you're making them do complex things. Because you're in complete control of what NPCs do, you can create complex chains of events, and you don't have to build up the infrastructure required by freeform NPCs. Their greatest downside is that they don't scale well. You have to plan and implement everything an NPC does, and can't as easily rely on procedurally-generated behavior as with freeform NPCs.
Whether you make freeform or scripted NPCs, there are a number of issues that you'll have to deal with. First and foremost is how you model their actions within the game world.
Many authors take the straightforward approach: fake everything. If an NPC is going to pick up an object, print "Joe takes the key" and move the key directly to Joe. It's fast, it's easy to code, and it lets you tailor what's printed when an NPC does something.
It also bypasses the world model, and can cause you problems later on. Imagine that you have a cup of coffee that gets heated in a microwave until it's too hot to pick up. You add logic to the world model to keep the player from picking it up when it's too hot. You'll also have to add that code to your NPCs' routines. Most interactive fiction languages, like Inform and TADS, let you make world-model rules like "you can't pick up a hot thing" apply equally to players and NPCs, but if you bypass that built-in mechanism then you'll have to make sure the same logic applies to every NPC.
If you do use a language's built-in support for managing NPCs through the world model, you'll want to replace the default action reports with NPC-specific ones. You'll also have to make sure that every new action and behavior you add to the world model works with both the player and the NPCs.
How will you keep your NPCs from seeming mechanical? You can give your NPCs a wide range of actions, so they don't repeat themselves as often and expose the underlying mechanism. You can also limit the amount of time the player will spend around an NPC. Arrange the plot so the player only has a few turns around the NPC, or locate any puzzles away from where the NPC is.
The biggest problem for NPC-heavy games is how noisy they are. Every NPC who's present with the player and acting will print reports that tell the player what they did, and by tradition each of those reports is in a separate paragraph. If you're not careful, you can generate so much text that the player is overwhelmed. Consider this partial transcript from The Battle of Walcot Keep.
You stand in a field of tall grass and nettles. Large patches of the field are trodden black and muddied, signs of recent sorties engaged and broken, of a battle neither lost nor yet won. A siege tower stands here in the mud, nearby to the keep's northern wall. The steep hillside stretches up to the north, and to the south lies the road to the main gate. Beyond the road lies a ditch, and then the hills on the far side of the valley. The sounds of battle crash in your ears.
Five royalist men-at-arms and two royalist archers are standing here.
Baron Geoffrey is sitting on the chestnut horse.
Two rebel men-at-arms, four rebel archers, and Lord Ranulf are standing on the north wall.
Two royalist men-at-arms and a ruddy royalist archer are standing in the ditch.
A stout royalist man-at-arms is standing upon the road.
A tall rebel archer's arrow flies true, hitting a small royalist man-at-arms squarely. A stout rebel archer's arrow flies true, hitting a small royalist man-at-arms squarely. A small royalist man-at-arms falls dead. A thin rebel archer cannot reach a small royalist man-at-arms. A tall royalist man-at-arms heaves with all his might, and inches the siege tower towards the wall. A thin royalist man-at-arms heaves with all his might, and inches the siege tower towards the wall. A large royalist man-at-arms enters the road. Gripping his blade, a sturdy rebel man-at-arms readies himself. A stout royalist man-at-arms enters the field. A comely royalist man-at-arms puts the wooden siege ladder against the castle wall. Geoffrey smiles grimly, and grips his blade. "They are weak; the keep will fall!" Ranulf calls to a small rebel man-at-arms, "Topple that ladder!"
You may want that sense of being overwhelmed. Kissing the Buddha's Feet, where the NPCs are supposed to get on the player's nerves, uses this to good effect. If you don't want to overwhelm the player, though, you'll need to find ways to cut down on the noise.
One approach is to collate reports. If several NPCs do the same thing, summarize what they do. TurnLarry comes in from the east.
Darryl comes in from the east.
Darryl comes in from the east.
intoLarry, Darryl, and Darryl come in from the east.
Another is to glue the report of similar actions together. If you have a dog who follows another NPC, stick their reports together. TurnTimmy leaves to the east.
Lassie, seeing Timmy leave, gets up and follows him.
intoTimmy leaves to the east. Lassie, seeing Timmy leave, gets up and follows him.
While that doesn't change the amount of text, it feels less noisy. A single paragraph is less visual clutter than several separate paragraphs. The trade-off is that the player is less likely to read reports buried in a long paragraph. Scan the excerpt from The Battle of Walcot Keep above and see if you can find two of the major NPCs talking. If the player absolutely needs to notice Lassie leaving with Timmy, leave it as a separate paragraph.
Combining Freeform and Scripted Techniques
If the freeform approach is better suited for NPCs carrying out incidental actions and the scripted approach is better suited for NPCs performing specific actions, can the two be combined to draw on the strengths of both approaches? As an example, let's pull Child's Play apart. If you haven't played the game and think you might want to, you should probably go play it before reading the rest of this article.
Child's Play is a game about a playdate where parents have brought their very young babies to play together. There are two main sets of NPCs, the parents and the babies. The parents converse among themselves and barely interact with the babies, while the babies crawl around and interact with each other.
The parents' conversation is entirely scripted. Every 10 turns or so, the parents begin a new conversation. Each conversation is a list of strings. Each string is printed in sequence until there are no more to print.
The babies are more complex. They're a mix of freeform and scripted behavior. Their freeform behavior lets them wander around randomly, play with toys, and react to each other. Their scripted behavior provides hints by helping teach the player how to be a baby. In all cases their actions are processed using the world model's logic.
(One side note: their wandering is not entirely random. So that the player will be more likely to see them interacting, the babies preferentially wander into rooms where the player or other babies are.)
For their freeform behavior, the babies were modeled as state machines. Each baby has a series of states defined mostly by what they're doing, such as holding a toy, chewing a toy, or standing up. They also have transitions from one state to another, and a probability that they'll make that transition. As an example, if Cassie is holding a toy, she has a 20% chance of dropping that toy and moving to the empty-handed state.
Each baby's state machine was tailored to fit their personality, so that their actions expressed personality. Cassie, the rambunctious baby, stands using furniture, moves along that furniture, and bangs toys on other toys. Watson, the quiet baby, barely plays with toys. Each baby's action reports, such as what is printed when a baby drops a toy, was also tailored to fit their personality. Cassie grabs toys excitedly; Watson gingerly picks up toys.
In some cases, the game swaps out a baby's state machine for a new one, especially when a baby has a specific goal in mind. In one chapter, Cassie seeks out a set of climbable blocks, pushing them together in one room until she can climb the entire set. That behavior is encoded in a new state machine that temporarily replaces her standard one.
Some of the babies respond to other babies' actions, including the player's. Watson sometimes flinches when Cassie sits down or throws a toy around. Jemison is the most notable example. Early on in the game, if the player or any other NPC takes a toy, Jemison becomes fascinated with that toy. He follows the player or NPC around until they drop the toy, at which point he grabs it.
Alongside those freeform behaviors are scripted behaviors which provide hints for the player. Most of those scripted behaviors occur at the beginning of chapters, when all of the NPCs have a known location. At the beginning of the first full chapter, Cassie is standing using a couch. When the player sees her, she will slide along the couch and into an adjoining room to demonstrate how babies cruise along furniture.
The mix of scripted and freeform behavior Child's Play allow the NPCs to perform a wide range of easily-extended actions, making them more believable, while providing for more hand-crafted sequences that give necessary information to the player.
If you're going to write a game with NPCs, where do you go from here? Start by deciding what your NPCs will do. Will they provide information to the player? Will they wander around, adding to the game's setting and atmosphere? Will they react to the player, or be more autonomous?
Once you've decided what your NPCs will do, you can decide how they'll do it. The more extensive a role NPCs will play, the more you should be willing to spend on complex underpinnings. Unless the point of your game is to explore new modes of NPC interaction and programming, the pragmatist in me encourages you to use as simple a model as you can get away with. It's far easier to add complexity to a simple model than to make a complex model simple. And if you are going to make a complex NPC model or build on an existing one, consider making a small test game to prove your model works before grafting it into your full game.
The true measure of your NPCs is how players react to them. Nothing beats having testers try your game and give you feedback on the NPCs. They'll notice things you overlooked and be able to tell you what does and doesn't work.