[i7] Modifying 'Please answer yes or no'

This seems like it should be doable without needing to import a whole extension. But I am unable to find an easy way.

I noticed Ron Newcomb’s Original Parser could be modified to change the message as needed. Also his or David Fisher’s Custom Messages means I would just pop in a change to LibMsg & I’d be good.

Now this-all works, but it’s full of special cases, checks, etc., and if I wanted to have anyone else talking, there’d be a big problem.

room 1 is a room.

to say-yes: say "'Yes-man.'";
to say-no: say "'Negative Nancy.'";

yes-no-only is a truth state that varies.

after reading a command:
	if yes-no-only is true:
		let W be word number 1 in the player's command in lower case;
		if W is "yes" or W is "y":
			now yes-no-only is false;
			say-yes instead;
		if W is "no" or W is "n":
			now yes-no-only is false;
			say-no instead;
		say "'[if number of words in the player's command > 1]I don't want a biography, just a yes or no.'[else]What? Quit mumbling! Yes or no.'[end if]";
		reject the player's command;

Rule for printing a parser error when the latest parser error is the I beg your pardon error:
	if yes-no-only is true:
		say "'It can't be that hard to decide. I'm a busy man. Get on with it, yes or no.'";
	else:
		say "Trying for a moment's peace, you involuntarily recall that awful conversation."

after printing the locale description for room 1 when room 1 is unvisited:
	now yes-no-only is true;
	say "'So, yes or no?' asks the aggressive bore who's lulled you to half-sleep."

But I really only need to change the yes/no dialog for a small change, so I’d rather focus on that. And unfortunately I can’t rules-debug to see what I can change…is there an easy way or variable I can change?

Thanks!

Do you definitely want the parser to be active while you are trying to get the yes/no response? Since you seem to be trying to block anything that isn’t yes or no at the time, I’d skip the parser and just ask for a keypress… unless for stylistic reasons, you still want the player to have to type the response and press return.

So if you’d consider a keypress, I’d throw ShadowChaser’s Useful Functions extension into your game, and do something like this:

[code]“Aggressive Bore demo” by Wade Clarke.

Include Useful Functions by Shadowchaser.

Hallway is a room. “Go east to enter the parlour.”

Parlour is east of Hallway.

aggressive bore is a man in parlour.

Every turn when location is parlour and aggressive bore is in location:
let answer be yesno_answer_with_question “‘So, yes or no?’ asks the aggressive bore who’s lulled you to half-sleep. (Press Y or N)[line break]”;
if answer is “NO”:
instead say “‘Negative Nancy.’”;
otherwise: [yes]
say “‘Yes-man.’”;
rule succeeds.[/code]
The yesno routine from the extension doesn’t accept any keys other than Y or N, so if you really want that extra response for pressing the wrong key, you’d have to modify it slightly. Or just extract it on its own and tweak it. But I really like this routine and some similar ones from the extension, and I use them often. As you can see, the resulting code is also easy on the eye and basically all in one place.

  • Wade

From a UI standpoint, requesting line input is better than keystroke input for this sort of thing – the player will be unsettled if the game switches modes.

For the built-in “if the player consents” query (which is line input), the prompt can only be customized through Custom Library Messages. (The message seems to be filed under Quit; I guess for historical reasons.)

Yes, that seems very clean. I’m glad you found that–I think with a few tweaks like you said, it can do exactly what I want. I’d always sort of hoped for this sort of can-opener extension, and it’ll be worth looking at the code, too. Thanks!

ETA: thanks Zarf for the additional explanation.

I don’t agree with that per se. My game Six has lots of these y/n keypress breaks and I don’t think anyone was unsettled. I think what may matter more is how you present the transition. Just subtle, little stuff, like where you put your line breaks. Or actually bolding the (Y/N) part may do it. In my example code in this topic, I didn’t do it gracefully, as the y/n question is almost attached to the same line as the dialogue, etc., and not really set out at all, but I was just doing a quickie mechanical example.

Apart from that, I find it’s easier to get these kinds of choices through keypresses in general because of all the work that has to be done at getting them from the parser, which is not very good at it. I feel klunky doing things like changing the prompt to a particular question so that I could then say ‘After reading the player’s command… If the prompt was (the quesstion)… if the text matches such and such…’ or words to that effect. Or using other filtering workarounds.

  • Wade

Why don’t you do something like this?

[code]Include (-

[ YesOrNo i j;
for (::slight_smile: {
if (location ~= nothing && parent(player) ~= nothing) DrawStatusLine();
KeyboardPrimitive(buffer, parse);
#Ifdef TARGET_ZCODE;
j = parse->1;
#Ifnot; ! TARGET_GLULX;
j = parse–>0;
#Endif; ! TARGET_
if (j) { ! at least one word entered
i = parse–>1;
if (i == YES1__WD or YES2__WD or YES3__WD) rtrue;
if (i == NO1__WD or NO2__WD or NO3__WD) rfalse;
}
PrintText((+ yes or no message +));
}
];

-) instead of “Yes/No Questions” in “Parser.i6t”.

The yes or no message is a text that varies. The yes or no message is “’[if number of words in the player’s command is greater than 1]I don’t want a biography, just a yes or no[otherwise]What? Quit mumbling! Yes or no[end if].’”.[/code]

All you have to do now is change the text to suit the purposes.

Hope this helps.

Wow! Thanks again–with what I know from Inform 6, this helps things click–& it looks like I’ll be able to modify it for other purposes, too.

To repost, I tweaked the code a bit to give the results I want. Apparently the # of letters in the command doesn’t get recycled/updated, so this is necessary:

Include (-

[code][ YesOrNo i j;
for (::slight_smile: {
if (location ~= nothing && parent(player) ~= nothing) DrawStatusLine();
KeyboardPrimitive(buffer, parse);
#Ifdef TARGET_ZCODE;
j = parse->1;
#Ifnot; ! TARGET_GLULX;
j = parse–>0;
#Endif; ! TARGET_
PrintText((+ yes or no message +));
if (j) { ! at least one word entered
i = parse–>1;
if (i == YES1__WD or YES2__WD) rtrue;
if (i == NO1__WD or NO2__WD) rfalse;
if (parse–>2) { PrintText("‘No biographies. Simple yes or no.’"); } else {
PrintText("‘No maybes. Yes or no.’"); }
} else { PrintText("‘What? Quit mumbling!’"); }
}
];

-) instead of “Yes/No Questions” in “Parser.i6t”.[/code]

Nonetheless, I can see how to add different dialogues for different NPCs, by changing the static PrintText commands to the ((++)) syntax you have. Which will be great when I write a game with >1 NPC!

So yay to me for figuring out my first I6 tweak & of course I couldn’t have done it without the initial code.

/stands on prow of Titanic and proclaims self king of world

I see what you’re trying to get. However, I’d suggest doing it like this.

[spoiler][code]“Test”

Include (-

[ YesOrNo i j;
for (::slight_smile: {
if (location ~= nothing && parent(player) ~= nothing) DrawStatusLine();
KeyboardPrimitive(buffer, parse);
#Ifdef TARGET_ZCODE;
j = parse->1;
#Ifnot; ! TARGET_GLULX;
j = parse–>0;
#Endif; ! TARGET_
if (j) { ! at least one word entered
if (WordCount() > 1) {
PrintText((+ multiple word message +));
}
else {
i = parse–>1;
if (i == YES1__WD or YES2__WD) rtrue;
if (i == NO1__WD or NO2__WD) rfalse;
PrintText((+ single word message +));
}
}
else {
PrintText((+ no word message +));
}
}
];

-) instead of “Yes/No Questions” in “Parser.i6t”.

The yes or no message is a text that varies. The multiple word message is a text that varies. The single word message is a text that varies. The no word message is a text that varies.

The yes or no message is "‘Enter yes or no.’> ". The multiple word message is "‘No biographies. Simple yes or no.’> ". The single word message is "‘No maybes. Yes or no.’> ". The no word message is "‘What? Quit mumbling! Yes or no.’> ".

Every turn:
say the yes or no message;
if the player consents begin;
say “Your command is: [player’s command].”;
say “Yes!”;
otherwise;
say “Your command is: [player’s command].”;
say “No!”;
end if.

Test me with “wait / yes or no / other / yes”.

The Testing Room is A Room.[/code][/spoiler]

This way the text can be handled at I7 level.

Hope this helps.

Thanks again–I actually had a section of code thought up for handling multiple people, but I didn’t want to text dump it all. What I have is something like this, using the ++ commands and a table e.g.

The yes or no message is “[context-based-yes-no]”

to say context-based-yes-no:
repeat through table of blatherers:
if npc entry is visible:
say “[yes-no entry]”;
continue the action;
say “Please input yes or no.”

This is pseudocode, but I think it jibes with what you have, as well as the silly special cases important to me. But I think your main point is important–the code as I have it is currently inflexible for more than one NPC & does not lend itself to I7 modifications.

In that case I’d suggest using rules rather than text. So something like this.

This is the yes or no rule: repeat through table of blatherers begin; if npc entry is visible begin; say "[yes-no entry]"; continue the action; end if; say "Please input yes or no."; end repeat.

You can them call this rule at I6 level like this.

ProcessRulebook((+ the yes or no rule +));

Hope this helps.

Thanks again! I have trouble organizing stuff into rules, but it is so powerful. It’s really comforting to know how much common-sense stuff I6 has despite not being I7’s natural language–stuff like ProcessRulebook.

I’ve been stumbling along here, but I’ve been able to see a lot more about the .i6t reserved files than before, so I appreciate it.

Also, instead of parse–>2, I was looking for

if (WordCount() > 1) { PrintText("'No biographies. Simple yes or no.'"); } else { PrintText("'No maybes. Yes or no.'"); }