Is it possible to have two "types" of conversation exist in a single source code?

Version 1.0 of my Inform 7 game “The Time Machine” used the basic Ask/Tell mechanism for conversation.

Instead of telling Watchett about something: try asking Watchett about it.

Instead of asking Watchett about "wells": say "'Always working too hard on his experiments, he is. I'm sure the doctor will make everything right.'"
Instead of asking Watchett about "experiments": say "'I wouldn't know anything about that. Mr. Wells was quite private about his experiments. Did all that in his workshop.'"
Instead of asking Watchett about "workshop door": say "'Locked. Always locked. Only Mr. Wells had the key.'"

I have been experimenting with Eric Eve’s conversation extensions to provide a more prompted and natural way to converse with the characters.

Based on Writing with Inform, Chapter 27, Section 9, I see that it is possible to have code that is compiled based on whether or not a particular extension is included.

Part Watachett

Chapter 1a -  New Conversation Mode (for use with Conversation Package by Eric Eve)

Chapter 1b - Old Ask/Tell Conversation (for use without Conversation Package by Eric Eve)

With this formatting you could have both ways of conversing in the source code but only one would be compiled based on whether or not the Conversation Package extension was included. In the example above it is Either/Or, you can converse the old Ask/Tell way or the new way using Conversation Package features.

But is it possible to have code for these two modes of conversation to co-exist?

Include Conversation Package by Eric Eve.

Part Watchett

Chapter - Suggestions (for use with Conversation Package by Eric Eve)

Chapter - Conversation (for use with Conversation Package by Eric Eve)

Part Humboldt

Chapter - Conversation (for use with Standard Rules by Graham Nelson)

In this case I’d like Watchett conversations to be handled by Eric Eve’s Conversation Package extension but let Humbolt’s conversations be handled by the old Ask/Tell code.

The goal is to be able to refactor each character’s conversations individually rather than have to modify all character’s conversations at once.

Thanks in advance.

1 Like

Glancing at the whole Eric Eve conversation ecosystem, it’s got a lot going on. Especially to someone like me who never uses this particular form of conversation.

However I have looked a bit at most of the extensions, and it seems to me (as is stated in Conversation Defaults docs) that its systems mostly kick in at the Report and After stages in the rulebooks.

This makes me think that any conversation you intercept – and completely deal with – with an Instead rule, will not enter the conversation extensions’ systems.

So if the person you want to isolate with the ‘old’ way of doing things is Humbolt, covering all of his talking with rules like

Instead of asking Humbolt about "wells": say "'Always working too hard on his experiments, he is."

might do it.

But there are lots of default Inform commands that lead into conversation, and Eric Eve’s extensions also have tons of hooks pulling conversation into them. The disadvantage of trying to run both systems at once is you’ll have to completely cover every type of hook with an Instead rule (or other mechanism) to intercept the lot in the case of Humbolt alone.

Is it worth doing this when you’ve taken the trouble to learn how to use Eric Eve’s system? From my quite outside your project perspective, I think it’d be a more comfortable programming task to do it all one way or the other. But in answer to the question, is it possible to run both at once – I’d say yes, but you need a comprehensive approach to scoop up all Humbolt’s conversation separate to Watchett’s. Also, running both at once will not require any lines like (for use with blah blah by Jane Blah). You’d just include all the Eric Eve extensions you’re using, then program Humbolt’s conversation from the ground up.

Someone with more experience with these extensions or conversations may chime in.


1 Like

I don’t think the (for use with...) heading method you’re describing can work. You can’t control whether an extension applies to some section of the source and not other sections; you can only control whether a section compiles at all based on whether some extension is available. I think. I think that’s how it works.

But it is possible to have multiple conversation types work in a single game! I did so in this tutorial game. I think it’ll be a really clever way for a non-tutorial game to distinguish characters.

I haven’t looked at the code in years, so finding out how I did this is going to be an adventure for all of us! Let’s see…

A Journey into the Past (you can skip this part)


Section - Making Conversation Work

[We'll see below that there are three NPCs in this game, each of whom "speaks a different language": Heather responds only to TALK TO; Casey responds to ASK/TELL; and Orchid has a choice-based conversation tree. Getting these systems to coexist can be accomplished simply (I hope) by modifying a couple of extensions.]

Include Conversation Framework by Eric Eve.

Include Quip-Based Conversation by Michael Martin.

The reject asking for talking rule is not listed in any rulebook.
The reject telling for talking rule is not listed in any rulebook.
The reject answering for talking rule is not listed in any rulebook.
The reject commanding for talking rule is not listed in any rulebook.

Instead of requesting something for something, try quizzing the noun about the second noun.

Instead of imploring something for something, try asking the noun about the topic understood instead.

So I’ve started out by including a couple of extensions and then deleting a few rules from them. The “reject” rules appear in Quip-Based Conversation and are supposed to enforce the quip-based model as the only permissible conversation mode. De-listing them is how I’m allowing multiple modes to exist, which is kind of like what you’re trying to do! Kind of!

Heather’s behavior is extremely simple, but for the sake of completeness, it goes like:

Instead of saying hello to Heather when the greeting type is explicit:
	say "blah blah blah Heather talks"

So, when I don’t want the Conversation Framework stuff to kick in, I just don’t let the “saying hello to” action do what Conversation Framework wants it to do in that situation.

Instead of speaking when the noun is Heather, say "Heather only responds to 'talk to Heather'. It's not that she's a boring person; she just doesn't have a lot to say."

“Speaking” is a type of behavior defined in Conversation Framework that includes asking, telling, quizzing, etc. Conversation Framework itself doesn’t seem to do anything with this definition? But it’s useful for just this sort of situation.

Casey responds to ASK/TELL in this way:

Instead of asking Casey about a topic listed in the Table of Casey Good Topics, say "[words entry][paragraph break]".

Instead of quizzing Casey about a thing listed in the Table of Casey Good Times, say "[words entry][paragraph break]".

Instead of informing Casey about a thing listed in the Table of Casey Good Times, say "[words entry][paragraph break]".

And then there are some tables. Pretty simple. But you can see how I made sure the relevant rules apply only to him.

Orchid has a quip-based tree:

Before speaking when the noun is Orchid, say "Here there's a reminder to try TALK TO or select a conversation option." instead.

The greeting of Orchid is Orchid-greet. The litany of Orchid is the Table of Orchid Talking.

And then you have her table and her quips and everything.

Let’s see if any of this is actionable.


Obviously none of the above is copy-and-pastable into your project, but some of the techniques may translate into strategies you can apply. The main thing is, you have dig around in the source of the extension and identify the part that the extension author wanted to apply universally. And then you must somehow compel that part to apply only in certain contexts.

You can hack an extension from within your project. If the relevant rule in the extension is named, you can de-list it with a not listed in any rulebook. declaration, as above. But then you might have to write a new version of that rule that does apply to the NPC you do want it to apply to…In which case sometimes it’s simpler to revise the rule, just like you can revise the Standard Rules, as explicated here.

Or sometimes you can just write a rule that circumvents an extension: Before asking Watchett about something: do this other behavior. Which is the main thing I did above.

Sometimes it is desirable or necessary to edit an extension to a point of near-unrecognizability. In such a case, rather than including the actual extension, you can pick and choose from the source code and paste in only the parts of it that actually work for you. (Also you can change whatever you want.) And then you can credit the extension author like this:

Report requesting the story file version:
	say "Plus a modified version of:[line break]Bonfires and Broomsticks by Mary Norton[line break]".

This might seem kind of skeevy but it’s totally fine. I have had to do it several times.


Personally, I think I wouldn’t try to run the different systems at once, I’d rather circumvent the issue in a relatively primitive but easy way.

If you don’t absolutely need to keep the current transcript verbatim intact during the refactoring process, and if you don’t set a lot of flags in different places in the old conversation, then you could just comment out (or conditionally exclude) the whole Humboldt conversation code and cheat your way around it, I think?

So, something like this:

Include Conversation Package by Eric Eve.

The Study is a room.

Part Humboldt

Humboldt is a man in the Study. [...]

Chapter - Conversation (for use without Conversation Package by Eric Eve)

[Alternatively, since we will always include the package, 
we could also just comment this whole chapter out.]

[old ask/tell conversation]
Instead of asking Humboldt about "expeditions":
	[... assuming we set some story flags here...;]
	say "'Oh yes, they were great fun.'"

Chapter - Conversation (for use with Conversation Package by Eric Eve)

[While we are refactoring the other NPCs, we just cheat our way around Humboldt by jumping.]
Instead of jumping in the presence of Humboldt:
	[... set any story flags here which would normally be set by conversation...;] 
	say "As if by magic, you feel the plot progressing."

Possible drawbacks:

  • if, elsewhere in the code, you checked something like “if we have asked Humboldt about ...”, that wouldn’t be true anymore (although the same already applies to “instead” anyway, so that is a moot point)

  • if you set a lot of flags at different points in time in the old ask/tell system, it would complicate the “cheat” (although of course you can put additional branches into the JUMPING rule, if necessary)

  • and of course you’ll have to remember to change any automatic “TEST ME WITH …” chains accordingly, to perform JUMP at the right time.

1 Like

@afterward Thank you so much for the example. The strategies you applied to “A Journey into the Past” give me hope that such a thing I’m trying to do is possible. I will have to take a look at the original source and determine if the benefits of figuring out how to make extensions co-exist outweight the time spent. But at least I have a path forward if I decide to go that route.

@severedhand When I started trying to figure out how Eric Eve’s extensions worked I created a separate Inform 7 file where I could do my conversation experiments. The goal was to get one charater’s conversations working with the Eric Eve extensions, cut and paste the code for that character into my original source code, and then work on the next character (my original source, being my first game, is a bit gnarly in sections).

However, since I only have four charaters so far, I might just get all four character conversations working in my conversation mini-game and then transfer the new code over the “The Time Machine” in one fell swoop.

@stjohnlimbo Good suggestion. I currently have Humbolt’s “new” conversation code commented out in my mini-conversation while I was debugging this issue. Combined with @severedhand’s suggestion this might be the way forward.