Questions about conversation handling

Hi folks!

I know I’m opening a big topic here but I really need help with writing conversation. I’ll post the questions I have here from time to time and as soon as something new comes up. I will edit this first post with your answers as soon as the question is answered.

[size=150]1. How can I add a check marker for a topic that has already been asked?[/size]

It’s good manner to give different answers each time a topic is asked about, especially when asking the same topic several times. For this we add a state column to the answer table to see which lines have already been asked. If all answers have been spoken, we resign to a table of standardized answers an choose a random line each time the topic is asked again from now on.

Carry out asking the shop owner about a topic listed in the Table of convo:
	repeat through the Table of convo:
		if the topic understood matches the topic entry and the state entry is false:
			say "[Answer entry][paragraph break]";
			now state entry is true;
			rule succeeds;
	choose a random row in the Table of asked topics;
	say "[reply entry][line break]".

Table of convo
topic 	state	answer
"topic 1"	false 	"answer_1_1"
"topic 1"	false 	"answer_1_2"
"topic 2"	false 	"answer_2_1"
"topic 2"	false 	"answer_2_2"

Table of asked topics
reply
"standard reply 1"
"standard reply 2"
"standard reply 3"
"standard reply 4"
"standard reply 5"

“The noun” always refers to an object; if you want a value instead, ask for “the number understood” or “the topic understood” or whatever type of value you want.

But in this case, checking if the topic is listed in the table selects the right row for you automatically. So you can just start using “the answer entry” and such without any further problems.

(Pre-emptively, it’s also “blank out the whole row”, not “blank row out the whole row”.)

Thanks! I’ve corrected the code and posted another question. The question about the topic status is still active.

Assuming you are using objects to represent your topics:

A topic can be addressed or unaddressed. A topic is usually unaddressed. [obviously "addressed" can be something else]

Then either write a global After rule to set the topic to “addressed” every time it’s asked, or (more likely) do separate rules for every topic depending on how often you want to be able to ask about each.

Also, this is slightly hacky, but you can get around having duplicate topic entries by using [one of][or]…[stopping], and then use text substitutions to trigger any code that needs to run on subsequent asks if necessary. For example:

[code]You ask the shop owner about cheese. He says, “[one of]We don’t have any cheese[or][flipout]I told you, we don’t have any cheese[stopping].”

To say flipout:
now the shop owner is enraged.
[/code]

(This also works with “addressed” above, though that can be hard to read and maintain.)

“Topic” is a built-in type, representing test which is meant to be parsed rather than printed (“the/-- apple/fruit”).

If you just want a check marker, you can make another column in the table (called “check” or something) filled with a truth-state–so all the initial values would be false. Then change the entry to true whenever the row is used.

If you want to check whether a topic has been asked about more than twice, you could make the column number valued. Add 1 to the value every time a row is invoked; then you can check whether the value in this column is at least 2. (I don’t think it would be feasible to put this in the rule header, though; you’d need some slightly more complicated code that first finds the appropriate row and then checks the counter entry.)

Right, I’m just making a suggestion based on the model the OP may have used. This is what I have done for pretty much everything I have done in Inform 7 that requires conversation or other text to be printed only once.

Just wanted to clarify, since putting that code snippet in naïvely could lead to mysterious errors. Inform is somewhat strange about aliasing type names: “a topic is a kind of thing” is totally fine, but “the foobar is a topic” then errors. And attempting to add any adjectives to the “topic” kind defaults to the built-in one, which can’t have properties or attributes (so “a topic can be quux” is an error).

I’ve added a “status” column which switches from false to true when the topic has been asked:

Carry out asking the shop owner about a topic listed in the Table of convo: [select row with state "false" if it exists, otherwise reply with standard answer] say "[Answer entry][paragraph break]"; now state entry is true.
How can I automatically select the row with the status “false”? You may also just hint to the appropriate documentation entry because I cannot find it somehow.

Carry out asking the shop owner about a topic listed in the Table of Convo:
    if the state entry is true, make no decision; [this is saying to Inform "this rule doesn't apply, the next rule in line should take it"]
    say...[your code here]
    now the state entry is true.

Another option is to use cycling/stopping text for your responses.

say “Bob says, ‘[one of]I think bread is cool[or]I’m not so fond of wheat[or]I answered that already. Let’s change the subject[stopping].’”

say “Rob says, ‘I love bread! I could talk endlessly about it! [one of]Especially rye[or]I’m a sucker for a good sourdough[or]Banana bread! Mm[or]Pumpernickel for when I feel daring[cycling].’”

If I understand you aright, try something like this:

Carry out asking the shop owner about something: repeat through the Table of Convo: [this goes through every row of the Table of convo; see §16.6 of Writing with Inform] if the state entry is false and the topic understood matches topic entry: [I haven't tested this, but I *think* "topic understood matches topic entry" should work; it is based on "if the topic understood includes topic entry" from "The Queen of Sheba," which is example 279 in the Inform docs--I think this is "(snippet) matches (topic)" which can be found in §18.33] say "[Answer entry][paragraph break]"; now state entry is true; break. [this ends the "repeat" loop, so the rule doesn't go on and hit the rest of the entries that match the topic and have state false; see WI §11.12]

Basically, if you need to match two columns at once, you can’t use the “listed in” shortcut; you have to repeat through the table and check both columns by hand. As I understand this isn’t actually any slower than using “listed in,” which repeats through the table and checks the one column. The potential issue here is that topic columns are kind of weird, but I think we can use “matches” to check them when we can’t use “listed in.”

…and as you can tell, there’s no one documentation entry that will tell you what to do here, it’s pretty well buried!

Sorry for keeping up so long with the answer.
I have tried this and basically it works. However, how can I print something else when all the state entries for the topic are true?
Here’s what I have:

Carry out asking the shop owner about a topic listed in the Table of convo: repeat through the Table of convo: if the topic understood matches the topic entry and the state entry is false: say "[Answer entry][paragraph break]"; now state entry is true; break.
Now I need to put this somewhere:

choose a random row in the Table of asked topics; say "[reply entry][line break]". for when all answers are depleted.
How can I accomplish that?

Change the “break” to a “rule succeeds” (i.e. stop the whole rule, not just the loop), and then put your extra code after the end of the “repeat” block.

Ha, that was easy! Thanks a lot! :slight_smile:
I’ll add the result to the first post!