Conversation responses from topic table keep including "there is no reply"

Hi all,

I’m new to interactive fiction and Inform 7. I’m trying to make a little conversation game, where you ask a character about topics listed in a table and you will get a different answer, depending on whether you have already asked them about the topic before.

Where my table is structured Topic, State (true/false depending on whether topic discussed before or not), Response1, Response 2, I have the following clause to decide which response to print:

Carry out asking Fafnir about a topic listed in the Table of Conversation:
** repeat through the Table of Conversation:**
** if the topic understood matches the topic entry and the state entry is false:**
** say “[Response1 entry][line break]”;**
** now state entry is true;**
** rule succeeds;**
** if the topic understood matches the topic entry and the state entry is true:**
** say “[Response2 entry][line break]”.**

It achieves my aim of choosing between Response1 and Response2, but underneath the desired response it then also prints “there is no reply”. For example, when asking about treasure for the first time, the game responds with:

>ask fafnir about treasure
Ah, yes, my pride and joy. It has taken me many of your human lifetimes to amass this hoard, and I shall guard it with my teeth and my claws and my fire.

There is no reply.

>

I am not sure what I have set up wrong in that rule above which makes it print the correct response and then also print a response as though it doesn’t recognise the topic I am asking about.

Can anyone explain it to me? Thank you very much for your help!

You need a “rule succeeds” on both if statements. Without that, the game thinks the carry out rule did not handle the job, so proceeds to the next one.

Hi Andrew,

Adding rule succeeds to the second if statement doesn’t seem to stop it printing “There is no reply” underneath. There’s still a bug in there somewhere even when both if statements succeed.

Is it something to do with the “carry out”? Should it be a “before” statement instead?

Thanks

Ah, right. Serves me right for answering without testing the code.

The “no reply” message is a report rule. For this action, there is normally no carry out phase, only report (because the action is purely about the response, not moving things around the model world).

You can add a carry out phase, but that never prevents the report phase from running.

You can do what you want by writing a report rule instead. The “rule succeeds” statements will end the report phase, so the game won’t move on to the fallback “No reply” report rule.

(By the way, use triple backticks ``` to format code on the forum.)

Report asking Fafnir about a topic listed in the Table of Conversation:
	repeat through the Table of Conversation:
		if the topic understood matches the topic entry and the state entry is false:
			say "[Response1 entry][line break]";
			now state entry is true;
			rule succeeds;
		if the topic understood matches the topic entry and the state entry is true:
			say "[Response2 entry][line break]";
			rule succeeds;

The examples in the manual use After rules or Instead of rules for conversation. Those work too.

This is an interesting conundrum, because actions (like Examine) whose chief function is to print a response rather than change the game world in any way might philosophically have at least generic response mechanics print their responses in the ‘Carry out’ rules for that action. This is indeed what happens in the Standard Rules for Examine.

This creates a difficulty however because, although it’s not emphasised in the I7 documentation, once the action has passed the Check stage, and has therefore succeeded, there is no way to stop it triggering the After and/or Report stages.

Using ‘stop the action’ in a Carry out rule, contrary to what one might expect from the description of this phrase in the documentation, does not stop the action continuing on to follow the After and/or Report rulebooks.

Examine deals with this by printing the object’s description, or the stock response 'You see nothing unusual about the [noun]." in the Carry out stage and having a Report stage which then runs but only prints a stock response in the case of a non-player actor doing the examining “[The actor] [look] closely at [the noun].”, printing nothing extra if it was the player doing the examining- the job having been already done in the Carry out stage.

The problem in replicating this way of doing things with the ‘Ask something about’ action is that the Report rule as written in the Standard Rules by default always prints the response “[There] [are] no reply.” .

There are however many of ways of avoiding this rule from firing after printing a reply.

(i) print the reply in a Before, Instead, After or Check rule. Instead or After rules will by default stop the action from proceeding to further stages without you having to say so, but Before or Check rules also allow the use of ‘stop the action’ to stop the action in its tracks without proceeding any further.

(ii) print the reply in a Report rule, as zarf suggests, then immediately terminate he Report stage with ‘rule succeeds’ to prevent the default response rule ever being reached

(iii) do it like Examine- print the reply or any stock response to the player asking in Carry out rules and remove the Report rule that normally prints the ‘There is no reply’ stock response to the player asking something about:

The block asking  rule is not listed in any rulebook.

This works fine because for asking something about, nothing is reported anyway for actors other than the player doing the asking. If we were dealing with an action like Examine that requires a report for non-player actors, we could either leave the existing report rule in place but intercept actions where the player is doing the asking with:

Report the player asking something about:
     rule succeeds.

or replace the existing rule entirely with one that prints a response only for non-player actors

My new report .....ing rule is listed instead of the .....   ....ing rule in the report ....ing rules.

Good form might (philosophically at least) suggest that if there is going to be a reply, the ‘asking something about’ action should be allowed to succeed, so the reply should be printed in the Carry out, After or Report stages by one of the methods described above.

Hi both,

Thanks so much for your explanations - they’re really useful, and I really appreciate the mechanics of it getting explained to me. Hopefully I won’t make this mistake again in the future.

I retried the code with an Instead rule and it seems to be working fine now :slight_smile:

Actually it’s not 100% true that the Report stage can’t be suppressed after reaching the Carry out stage, but it requires a little I6 hackery to switch the action to ‘silent’ mode, as normally invoked by phrases such as ‘try silently taking the cookie’.

‘Try silently…’ sets the I6 global variable “keep_silent” to true and this is then used when an action begins to set a specific action processing rulebook variable “action keeping silent”. This is done by way of setting element 1 of a 6-element → array Details_of_Specific_Action, then calling a routine WORK_OUT_DETAILS_OF_SPECIFIC_R, which sets this and the other specific action processing rulebook variables held in this array . When the Report stage is reached, if ‘action keeping silent’ is found to be true, the entire Report stage is skipped.

So:

To complete the action silently: (- Complete_Action_Silently(); -)

Include (-

[ Complete_Action_Silently;
keep_silent = true;                        ! this is the global keep silent flag
Details_of_Specific_Action-->1  = true;    ! this is the keep silent flag for the current action processing rulebook being worked through
WORK_OUT_DETAILS_OF_SPECIFIC_R();          ! this sets the rulebook variables
rtrue;
];

-)

means that we can now use ‘complete the action silently’ at any point in the action to suppress the Report stage, e.g.

Carry out asking Fafnir about a topic listed in the Table Of Conversation:
	## complicated code to say the reply ##
	complete the action silently;

Many Report stages in the Standard Rules are written such that when they run, if the global keep_silent flag is simply set to true then output is suppressed, but ‘Report an actor asking something about’ isn’t one of them, so to suppress output the entire Report stage must be removed, replaced or skipped by this or another method.

One method requiring no I6 hackery would be to use a global variable to set the ‘action keeping silent’ rulebook variable after returning from the stage in which silence is set (unfortunately the ‘action keeping silent’ variable is not directly accessible within the stage rulebooks- hence the I6 hackery above) e.g.

global_silence is a truth state that varies.
	
To complete the action tacitly:
	now global_silence is true;
	
A specific action-processing rule (this is the enable suppression of report stage rule):
	if global_silence is true:
		now action keeping silent is true;
		now global_silence is false.
		
The enable suppression of report stage rule is listed  before the after stage rule in the specific action-processing rules.

This method has the disadvantage that, unlike the I6 method, it will not work correctly if another action is somehow invoked between setting the global variable and reaching the rule that sets ‘action keeping silent’. If this happens, this intervening action will become silent instead of the intended one.

1 Like

Or you can just write an After rule. If that succeeds then the Report stage rules won’t be run. That’s what they’re for, after all.

1 Like

:grinning: Yeah, but less fun!

1 Like