Part A (§1): The BasicsKnowledge and Conversation
§1 The Basics
(Advanced NPC Implementation, Part 2a)
s developers, we can put forth a great deal of effort while trying to make an NPC appear believable. We can make the character walk around randomly. We can make him steal items that are lying around. We can even program the character to scribble graffiti on walls at significant locations. It's true, a character can be designed to do just about anything imaginable, but there is one aspect of NPC design that will, above all others, make or break the believability of an NPC: conversation.
A successful implementation of a PC-NPC conversation is no small task. Many developers have tried and failed to create believable dialog. Obviously, success at this bares great dependency upon the author's writing skill. Conversely, a well-written manuscript can be implemented poorly. The truth is, a text adventure without code is just text. Code and prose are equally important in interactive fiction and the two must complement each other to truly be effective.
The purpose of this three-part article series is to identify the major coding techniques used in the development of talking NPCs and give examples of implementing some of these. Additionally we will cover advanced techniques such as uniting knowledge and information, separating information from conversation, morphing conversation topics, conversation scripts, and implementing knowledge that is learnable. First, a disclaimer:
In interactive fiction, complex puzzles often have multiple solutions. The similarities between life and art are ever obvious in this regard, since complex coding objectives often can be accomplished by multiple techniques. As a general rule of thumb, the more complex the objective, the more diversified are the possible solutions. Since this is an article about "advanced" techniques in NPC conversations, the variations and alternate implementations abound. It should be noted that the techniques covered in this article work for me, but my way is not the only way. If you, as the reader, see another technique then feel free to implement it.
Now that that stuff is out of the way, let us begin slowly by touching upon the three major techniques used to implement interactive character conversations: Menus, keywords, and topics.
The Menu System
A commonly used method of implementing conversation is the menu-based system. There are several advantages to using this technique:
There are also some disadvantages to this technique:
This is not to say that the menu system is not worth considering. In fact, it has been implemented with great success in a few choice works. It is, however a replacement for what the standard library offers, the Ask/Tell/Answer paradigm, and will not be discussed further in this article.
Nearly every other conversation technique is based upon the Ask/Tell/Answer model. At its most basic implementation is the use of keywords...
Using Ask/Tell/Answer (With Keywords)
As stated above, the standard library implements a basic conversation framework by defining three communication verbs. These three verb are 'ask,' 'tell,' and 'answer' (or say) and they are handled traditionally in the NPC's life property. For the 'tell' and 'ask' forms, the first significant keyword is stored in the library variable 'second.' For the 'answer' form, it is stored in the variable 'noun.' Take the following as an example:
See how the keyword 'hello' is handled differently depending upon the verb used to reference it:
Alone, this technique is fairly limited, but it is also one of the most widely used methods for implementing conversation that you will find in Inform games. As such, there are various methods of making it somewhat more powerful. The consult_from and consult_words variables, for example, can be used to "look ahead" and example more than a single word. To demonstrate a starting point for diversifying the keyword technique, let's focus on the ASK form of communication in the next example:
Now the keyword 'hello' can be put into a specific context:
Obviously the above example isn't as useful as it could be since it is too dependent upon word order. For instance,
will NOT be matched by the routine in its present form. Certainly it could be modified to scan for words despite order, but the more we pattern match, the more we are duplicating code that exists in the parser. For conversation topics that are more than a single unique keyword, there is a better way.
Using Ask/Tell/Answer (With Conversation Objects)
Inform is an object based language. The rooms the player visits are objects, the items that are gathered are objects, and the very NPCs that exist in the game are objects. Not surprisingly, all of these things are accessible through the game. We can look at the room we are in, pick up a hammer that lies on the floor, and talk to the NPCs. Each of these objects exists in the game world. One of the more allusive concepts for a new Inform developer to grasp is that objects do not have to actually be present in the game at all. They can, instead, be abstractions. Use of these non-existent objects is the third, and most powerful method of implementing NPC conversation, since it opens the door for numerous other techniques.
Let us set the stage for more advanced techniques by walking through a thorough example of basic conversation objects. First, we can create a base class from which all conversation objects will be derived:
Not the most impressive line of code, but it is a step in the right direction. In fact, what it accomplishes is significant. We can now, for instance, write a fully qualified scope rule to determine if an NPC "owns" a specific conversation object and extend the 'ask' verb to use that rule.
The TopicInTarget() routine (scope rule) will pull into scope any KnowledgeTopic derived object that is a child of the character being questioned. In this way we can define what the character "knows". Additionally, notice the definition of the CommonKnowledge object. Topics that are placed within this object are also pulled into scope. All characters know topics that are classified as "common knowledge." Here is an example of two topics. The first, "beauty," is a child of the CommonKnowledge object and so is known by all characters. Only the mirror knows the second, "snowwhite":
As you can see, using knowledge objects allows us to fill the 'name' property with the keywords that can reference a topic, just as we would a table or a chair. With this technique, the variable 'second' no longer holds the keyword, but points to the object that was recognized. The life property must be changed to reflect this:
For the sake of example, and to verify that our new scope rule is working how we intended it, let's create another character coded almost exactly as the mirror:
Now we have two characters to converse with. Note that, like the mirror, the guard is also coded to respond to the 'snowwhite' question. It'll be up to our scope rule to determine if he knows about the topic. Since he does not, this portion of his life rule will never be called and the text, although defined, will never print:
That was what we expected. The guard knows nothing of 'snowwhite.' Our new scope rule is pulling in the appropriate knowledge for the appropriate character.
On to Advanced Techniques (Concluding the Basics)
The topics discussed in this section have set the stage for a discussion of more advanced techniques. In §2 we will begin to delve into more advanced topics that build upon what we have learned so far. For readers that wish to further contemplate the material of this section, I highly recommend a review of Roger Firth's Infact page. Specifically, the conversation section found at "http://www.firthworks.com/roger/infact/convers1.html" is of immediate relevance.
And now, on to section 2...
§2b: Advanced Techniques
Pronouns on Steroids