Puppy Power – Realistic Parser NPCs

After “Writing Graceful Parser NPCs”, people asked me to write more about in-depth NPC design.

My primary example will be the puppy from Beet the Devil. This should be reasonably spoiler-free, so don’t worry if you haven’t played yet.

For people who haven’t played, here’s a transcript that shows off some of the puppy’s early-game behavior. [Skip past the transcript]

Beet the Devil cover - shows a farmer throwing a beet at a shadowy demon head, while a big-eyed puppy watches from the bottom[Transcript starts]
The puppy bumbles out of the hay and pounces on your boot, wagging its whole rump enthusiastically.

>pet puppy
The puppy leans happily into your hand.

The puppy sniffs the great big pile of hay.

>pet puppy
The puppy makes a happy wuffling noise when you pet it.

The puppy lowers its head to sniff intently at the ground. Giving a sudden, high-pitched bark, it dashes off to the south.

>s

Garden
It’s not dawn yet, but there’s a soft grey glow in the easterly sky framing the widow’s house, just enough light to stumble around without too much trouble. Great big ruts in the earth ripped out most of the potatoes, the peppers and tomatoes have been scorched to a shrivel, and the leaves are fried straight off the carrots and onions, not to mention the celeries. The mushrooms look sauteed, the zucchini looks worse, the artichoke stinks, the brussels sprouts stink worse, and even the turnip bush’s not doing so well.

The barn’s off to the north way, and that’s where the bird dog usually stays. There’s a small door you can get in.

The small puppy is here.

Still rooted, a single beet sits in the center of its row. Alone of every vegetable in this garden, it looks untouched by demoniac wrath, but appearances are deceiving and you could be wrong.

The puppy sniffs around a bit in the dirt near the sad zucchini plant before starting to dig. After pitching around dirt for a bit, the puppy unearths an old rawhide bone.
The puppy sniffs your left boot.

>x puppy
It’s a chubby brown and white pup with spots like the bird dog and a real waggy tail.

The puppy discovers a rawhide bone nearby. The puppy pounces joyously on the rawhide bone. Making a happy “rrrRRRrrrRRR” sound, the puppy flops down on its stomach, pins the bone under one foot, and starts gnawing away at the rawhide.

That puppy looks properly distracted, and it probably won’t be going nowhere for a while.

>get puppy
You scoop up the puppy in both hands. It’s awfully wriggly!

You are now holding the small puppy, though it’s plain that the puppy wishes you weren’t.

>get bone
The puppy turns its head away and tries to dodge you, but you take the rawhide bone away from it anyway.

The puppy whines and wiggles. It’s quite an armful!

>drop bone
Dropped.

The puppy paws urgently at your nose. It has scratchy little feet.

>z
Time passes.

The puppy struggles frantically to get down.

>z
Time passes.

With a bark of triumph, the puppy leaps out of your arms and lands on the ground. It wags its tail wildly in delight!

>z
Time passes.

The puppy discovers a rawhide bone nearby. The puppy pounces joyously on the rawhide bone. Making a happy “rrrRRRrrrRRR” sound, the puppy flops down on its stomach, pins the bone under one foot, and starts gnawing away at the rawhide.

That puppy looks properly distracted, and it probably won’t be going nowhere for a while.

[Transcript ends]

A puppy created with purpose

Obviously, the puppy takes advantage of one of the graceful handling techniques from last time – specifically, #6 – Create a communication gulf between NPCs and the player. No one expects advanced logic or excellent conversational skills from a puppy. Yet compared to many parser NPCs, the puppy feels very alive.

Four specific qualities create this illusion:

  1. Active – The puppy acts on its own (sniffing things, digging in the dirt).
  2. Reactive – The puppy reacts to the player’s actions (such as when it is petted or picked up, or when the rawhide is taken away).
  3. Goal-Oriented – The puppy displays goals and goal-seeking behavior (exploring the area, trying to keep the rawhide).
  4. Randomized – Messages related to the puppy have multiple forms rather than just one form (such as the two petting reactions above).

1. Active

People take actions of their own accord. NPCs that take actions of their own accord will seem more alive.

For the puppy, I made a rule that checks the puppy’s current status every turn to figure out what it should be doing. (Appropriately, in Inform 7, this is accomplished with “every turn” rules.) To figure this out, the game runs through a prioritized list of conditions, like so:

  • Is the PC carrying the puppy? If so, struggle to get free!
  • Is the puppy standing on something? If so, jump down!
  • Is the rawhide bone near the puppy? If so, grab it!
  • Does the puppy have the rawhide bone? If so, chew on it!
  • Is the puppy in the Garden when the rawhide bone hasn’t been unearthed? If so, dig it up!
  • Is the puppy in the location of the PC? If not, go find the PC!
  • (if a random chance succeeds) Does the puppy have somewhere to go right now? If so, head over there!
  • (otherwise) It must be playtime! Go play, puppy!

The “puppy play activity” is also fairly detailed – it checks things like whether the puppy is holding something in its mouth and whether or not the puppy can pick up anything nearby. (My favorite bug from this game involved the puppy picking up a demon and running off with it.)

2. Reactive

People react to other people’s actions. Having customized reactions to the player’s interactions will make NPCs seem more alive. Leaving the default messaging in place will cause NPCs to seem robotic.

By intercepting actions directed at the puppy, I can write messaging that causes the puppy to react to the player’s actions. (This is mostly done with “instead” and “after” rules in Inform 7). The puppy has special reactions to:

  • take puppy
  • put puppy in (something)
  • drop puppy
  • give (something) to the puppy
  • show (something) to the puppy
  • kiss puppy
  • pet puppy
  • rub puppy
  • attack puppy
  • flour puppy (not a common verb!)

Fortunately, puppies are pretty content to do their own thing, so the puppy doesn’t have to react to many of the player’s actions in order to seem realistic.

Humans are significantly more opinionated. (A puppy would not complain about someone walking across a pristine white carpet without taking off their muddy shoes, but the homeowner can at least be expected to arch an eyebrow.) The same kinds of rules (instead/after) can be used in this context, too, as long as they are preceded by a check to make sure that the NPC is present.

For even more realism, if you have two NPCs present, cause them to react to each other as well as the player. The easiest way to do this in Inform 7 is to add additional clauses into the “every turn” rule controlling the initiating NPC. For example:

if (the location of the cookie jar is the location of the six-year-old) and (the cookie jar is closed):
    say “The six-year-old opens the cookie jar.”;
    if the music teacher is in the location of the six-year-old:
        say “The music teacher closes the cookie jar. ‘Practice first!’ she commands.[paragraph break]The six-year-old looks disappointed.”;
    else:
        now the cookie jar is open.

This gives the illusion of a reaction from the music teacher, but from a coding perspective, the response is just built into the six-year-old’s original action.

3. Goal-Oriented

People strive to achieve goals. NPCs with goals will seem more alive than NPCs who passively wait to respond to the player.

This is related to, but not the same as, being active. It’s possible for an NPC to take action without those actions being goal-oriented. For example, an NPC could walk up and down a set of office hallways (active), but unless the player can see a reason why the NPC is walking up and down the hallways (searching for a lost keycard? delivering the mail? getting some exercise?) then the NPC isn’t goal-oriented.

Programmatically speaking, the puppy is relatively complicated on this front. The puppy has a few different potential goals, all implemented by the if-then structure (get down if it’s being carried; wander around if it’s searching for something; chew on the rawhide if it has access to the rawhide).

But giving your NPCs goals doesn’t have to be a complicated process, and it’s often more a factor of writing than coding. If a given NPC wants something, and the NPC’s actions and reactions are aligned toward that goal, the NPC will seem more alive for it – even if the goal is as simple as “make this annoying person go away” or “pat the bunny” or “finish my burrito”.

4. Randomized

People don’t give the same responses to the same stimuli every time, or take the same actions in the same way. NPCs will seem more alive if their messaging contains random elements.

Almost all of the puppy’s messages are randomized to give it a more “living” quality. For example, here’s one of the messages from a puppy that is currently being held.

if a random chance of 1 in 2 succeeds:
    say “The puppy paws urgently at your [one of]shoulder[or]arm[or]hand[or]face[or]nose[or]chin[at random].  It has scratchy little feet.”;
otherwise:
    say “The puppy licks all over your [one of]nose[or]face[or]neck[or]ear[or]chin[at random], finishing up with a curious nibble.  Ugh, puppy slobber!  Argh, sharp little puppy teeth!”;

There are 2 core variations leading to 11 different messages. I’m also taking advantage of a feature of Inform 7, which is that a textual [at random] will not produce the same message twice in a row.

If someone picks up the puppy and waits for it to struggle free three times in a row, they might get the same response on the first try and third try – but that’s still a huge improvement over seeing the same message all three times.

Why make this effort? Because brains respond to novelty. If we read the same sentence twice, we won’t give it the same attention the second time around – unless it’s been changed up a bit. Taking the time to produce variations will increase player attention, which will in turn increase the seeming reality of our NPCs.

Keeping Perspective

I love writing NPCs – and writing this puppy, in particular, was a blast. But there’s a reason why I’m enthusiastic about ways to evade full implementation of human beings. The puppy is not a fully implemented NPC, and its code is… big.

Here’s a sample chunk:

The small puppy is a puppyproof male pup in the Wings. “The [if the small puppy is floured]ghostly white[otherwise]small[end if] puppy is [if the puppy is carrying the rawhide]flopped down nearby and completely occupied with chewing on a rawhide bone[otherwise if the puppy is carrying a thing]nearby with [a list of things carried by the puppy] in its mouth[otherwise][one of]here[or]not too far away[or]nearby[or]nearby investigating [a puppy interest][at random][end if].” The puppy can be noticed or unnoticed. The puppy is unnoticed. The description of the puppy is “It’s a chubby [if the puppy is not floured]brown and [end if]white pup with [if the puppy is not floured]spots like the bird dog and [end if]a real waggy tail[if the puppy has a rawhide bone]. It’s flopped down on its stomach and chewing on a rawhide bone[otherwise if the puppy has something]. It’s carrying around [a list of things carried by the puppy][end if].” The puppy has a number called wiggliness. The puppy has wiggliness 0. The puppy has a number called alertness. The puppy has alertness 0. Understand “puppy” and “white” and “chubby” and “tail” as the puppy.

The puppy is a major component of Beet the Devil, and it deserves all the code space it received. But it’s important to keep your priorities in mind and ensure that your time spent on NPCs will properly serve your game.

When I was first starting out in Inform 6, I spent a ridiculous amount of time working out conversations with a random passenger on the bus while I was building my first game. The passenger wasn’t important, and I don’t think the conversations weren’t particularly interesting. But I didn’t want my NPCs to be robotic, and an empty bus during rush hour seemed unrealistic, and I thought people had to be able to hold conversations.

If I were doing it again, I would still put people on the bus – but I’d deemphasize their presence, and if the player tried to talk with them, I’d establish that they didn’t want to talk to the player. Something like this:

[Pseudotranscript begins]

City Bus
Several passengers occupy the blue plastic seats. The air smells of industrial soap, body odor, and the lost ghosts of French fries. The sounds of car horns push past the engine’s uneven rumble.

>x passengers
The passengers sit in ones and twos, reading their books or staring out the dingy windows.

>ask passenger about bus
You try to ask a question of a woman in a brown leather coat, but she shakes her head and shouts back, “I can’t hear you over the bus!”

>ask passenger about bus
You try to ask a question of a man with wispy grey hair, but he only tightens his lips and turns the next page in his book.

[Pseudotranscript ends]

With a few additional atmospheric messages – people getting on and off the bus, for example – and a reasonable set of customized responses to commands like touch, attack, and hug, these bus passengers will cover all four of the key points for realistic NPCs:

  • active (they get on and off the bus)
  • reactive (customized responses to attempted interactions)
  • goal-oriented (they want to be left alone, and presumably get to their stops)
  • randomized (see the random individual “passenger” reactions)

What’s more, heavy reliance on technique #4 from the prior postDesign NPCs who don’t want to interact with the protagonist – has saved me from spending unnecessary amounts of time on these NPCs, so now I can go on and write the rest of my game.

I hope this helps. If you have more questions about designing parser NPCs, let me know!

Bookmark the permalink.

7 Comments

  1. I think a point that’s worth stressing – it’s implicit in almost everything you’re saying, but I don’t think you specifically state it – is that people are highly context-dependent, more so than the medium size dry goods that typically populate game-worlds. The more visibly context-dependent they are, the more likely the player is to think (or even care) about them as people.

    This can work in negative ways (it’s jarring if people do things that conspicuously don’t make sense given current conditions) and positive ones (contextual changes make NPCs appear reactive to the environment as well as the PC).

  2. Shameless self-promotion, but in Sparkle I had a dog NPC which has a lot of similar properties to the one described here. The code starts here: http://nitku.net/if/sparkle/source_98.html and spans a couple of pages from there on.

  3. I love your insight and taking the time to post these gems for Inform 7. Really helpful. I’m trying to get my two daughters interested in IF and this will help.

Leave a Reply to Carolyn VanEseltine Cancel reply

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