The Mortification of Conversation
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.