Not all dialog in IF follows the same structure, as each discussion does not serve the same goal, just like in real life. Some conversations are for fulfilling social needs (relieving boredom, establishing social harmony, making friends). Others are for obtaining information, or obtaining goods or services. Still others are initiated by people besides yourself to get you to do something or give something. Yet, in IF, usually conversations are one-size-fits-all and cut right to the chase. Either you need something or the NPC needs something, without even a “Hi” or “Bye” mixed in.
It’s important to keep in mind the motivations of the NPC when planning your conversations. Of course the NPC exists for a specific game purpose, but the NPC brings his or her own personality and preferences to play. Say that you have an NPC that serves largely to explain some of the strange goings-on in the mysterious mansion. He could be a historian of manses in the South with unrequited love for Vicky, a manor-owner’s daughter. When the player interacts with this NPC, he dispenses background information readily, but requires you to find out more information about Vicky before he reveals the secrets of her father’s palatial residence.
Not all NPCs should dispense whatever the player wants to know, or do whatever the player needs to have done at the drop of a hat. They must be convinced, either through ask/tell actions, or displaying of objects (say, an incriminating photo — which is an idea I got from some old RAIF posting), or by the PC befriending them, like bringing a blackberry cobbler to a hungry recluse.
This is something I’ve learned while designing the characters for Seasons — each serves a game purpose, and each has his or her own motivations, which makes fulfilling the game purpose a challenge for the player.
If you can design you game without conversation, do it. Nothing has caused me more grief than designing a realistic method of conversation. It’s not really the concepts that I’ve had to wrestle with, but rather the implementation. It’s been one of those bad days extended over several months. You know those days, that after you’ve broken your arm, been dumped, lost your keys, and got in a wreck, it finally looks like it’s stopped raining — and then you get hit by lightning.
I’m using the ORLibrary, and it’s pretty darn amazing for what it lets you do. Conversation pools, related topics, NPCs that can talk on their own — heady stuff. I’ve spent a long while learning how to speak its language and I’ve made it to the advanced tourist level, where I’m going into restaurants outside of the major cities and ordering local cuisine.
Anyhow, I thought I’d share a few code samples to show you what a few good topics look like if you’re using the various NPC conversational modules and Inform 6.
class topic_c class ORKnowledgeWeb; !-- For talking to James topics topic_c pctopics_c with KnownBy manexp, context cbman; !-- James' topics talking to player topic_c cbtopics with KnownBy cbman, context manexp;
What we’ve done up above is create topic pools for all the topics the player will use to talk to James, and for all the topics that James will use to talk to the player (James is cbman; the player is manexp). This is a good thing, because if you ever need to forbid a character from talking about a topic, you can simply move it out of that character’s pool. On a related note, say that you have a topic that needs to be discussed by an NPC, but not until certain other things happen first. You keep this topic in some other location and move it into the NPC’s pool at that time.
Here’s how individual topics that the player can talk about look:
topic_c names_c "names" cbtopics with name 'name' 'his' 'himself' 'man', query "~Who are you?~ you ask.", topicinformation [; !-- Prevents PC from talking about topic he just asked about. if ((action == ##AskTopic) && (manexp.prevact == action)) move who_p to hldclz; print "He looks you up and down and extends a hand. ~The name is James. Yours?~"; ], initiatable false, RelatedTopics nam_p; topic_c who_p "who" pctopics_c with name 'who', topicinformation "~Who are you?~ you ask.", RelatedTopics names_c;
If that looks complex, don’t worry. It is.
The way conversation works in the ORLibrary is that you can either Tell an NPC <topic>, or you can Ask an NPC <topic>. I’ve rejiggered it so that the Talk command tells the NPC a topic that the PC currently knows. This saves the player from having to think, “What do I say now?” However, that still leaves open Ask. Hence, the complexity.
First, note the multiplicity of names for the names_c topic, known by the NPC James. Having many names for a topic is critical for the asking to work well. In this example, “Ask man about his name”, “Ask man about himself” and “Ask man about man” all cause this topic to be chosen. Once this topic is chosen, its query (what the PC actually says to the NPC) is printed.
The topicinformation is the response of the NPC, the main text that you want to display. Like any other property, it can be a text string or a routine. Here, I needed to make it a routine to handle the fact that the player could get to this topic through two ways: Talking or Asking. That is to say, the player could type:
Ask man about his name
Talk to man
And this topic could display either way. The first way directly calls this topic; the second finds a topic that the PC currently knows (which could very well be who_p, and that in turn causes the NPC to respond with names_c).
I needed to make sure that if the player asks the man his name, that this topic doesn’t hang around for the player to stumble across through ordinary Talking interaction. Thus, the comparison line:
if ((action == ##AskTopic) && (manexp.prevact == action)) move who_p to hldclz;
If the PC is asking the NPC this question, then the who_p topic must be moved out of the PC’s topic pool. (Otherwise, you have the embarrassing situation where the PC asks a direct question and gets the NPC’s response, and then the PC can Talk to the NPC and the same topic displays.) Hldclz is a generic hidden room with no entrances and no exits that I’ve used to store objects no longer used by the game.
Lastly, the topic’s print statement fires no matter how the topic was reached.
Of course, this is just the beginning. Sometimes you’ll need a topic to change based on what the player has done or said previously. Say if the player has broken his arm climbing a tree, you’d want to change the response that an NPC says about climbing the tree for a better view. If you brain hasn’t exploded yet, hang around. I’ll put up a more involved example eventually that will definitely cause cranial detonation.