Talking to NPC

i checked two a bit two extensions about talk…but i somehow dont find them intuitive perhaps its bit too late at 3 am…now i almost finished my own talk procedure but i have a question is it possible to wait for user input within an action? i guess i have stages within action and i want user to further elaborate on his intentions…so carry out: …would need to wait for user input at some point. is that possible?

carry out talking:
	say "What a nice day";
	wait for player's command;
	after reading player's command:
		...while eggs are not eggs:

the upper is prefered way to do it but i can alter code.
as

After reading player's command:
	if something true
	...while eggs are not eggs:

but would realy want first solution if possible …Thank you

The main loop of a running Inform 7 game is (more or less):

  1. get player command input
  2. parse player input to determine which action should be executed
  3. execute the determined action
  4. process impact of the executed action

A rule such as a carry out talking rule is handled as part of step 3. Getting new input is part of step 1. Trying to obtain new input in the middle of executing an action is working very much against the grain of Inform 7, and it will be an uphill battle for you all the way. This is not likely to be a satisfying experience or to deliver satisfactory results.

Without knowing more about what you’re trying to do, it’s difficult to give targeted advice. However, my question is: Why you want new input in the middle of an action? In the absence of more information, the answer that makes the most sense is that you want the player to enter a topic or an object, i.e. some subject of conversation to which the NPC can respond.

The normal mode for this type of interaction is to have the player input the subject as part of the command. For example, the command >ASK TURTLE ABOUT RABBIT specifies the NPC (the turtle) and the subject (the text “rabbit”) at the same time. If you want to allow player input that consists of the subject only, you can set up some actions that work together to track the game state with respect to conversations. This will let you work with the grain of Inform 7 instead of against it.

Here is an overly-simple example that might be helpful as a starting point. Note that this is in no way a full-fledged conversation system:

"The Basics of Talking"

Beginning a conversation with is an action applying to one thing. Understand "talk to [someone]" or "t [someone]" as beginning a conversation with.

Instead of beginning a conversation with:
	try talking to the noun about "hello" instead.

Talking to it about is an action applying to one thing and one topic. Understand "talk to [someone] about [text]" as talking to it about.

Mid-conversation is initially false. The conversation partner is an object that varies.

First carry out talking to someone about:
	unless the noun is the player:
		now the conversation partner is the noun;
		now the command prompt is "(talking to [conversation partner])>>".

Carry out talking to someone about:
	if mid-conversation is false:
		now mid-conversation is true;
		say "(You are now talking to [the conversation partner]. Say 'bye' to end the conversation.)[line break]".

Last carry out talking to someone about "bye":
	say "(You stop talking to [the conversation partner].)[line break]";
	now mid-conversation is false;
	now the conversation partner is nothing;
	now the command prompt is ">".

Talking about is an action applying to one topic. Understand "[text]" as talking about  when mid-conversation is true.

Instead of talking about:
	try talking to the conversation partner about the topic understood instead.

Lounge is a room.

Bob is a man in Lounge.

Report talking to Bob about "hello":
	say "Bob looks at you in surprise. 'Hello,' he says."

Report talking to Bob about "talking":
	say "'Sure, I can talk,' says Bob."

Report talking to Bob about "speech/speaking":
	say "'Isn't that what we're doing right now?' asks Bob."

Report talking to Bob about "discussion/discussing":
	say "'If you want a real discussion, you need someone with more programmed responses,' says Bob."

test me with "talk to bob / talking / speaking / discussing / bye / programming".

You may want to read the built-in documentation, especially the Recipe Book’s chapter 7 Other Characters, which has much, much more to say about conversation.

6 Likes

thank you
i was having several options with grouping variables and code in mind …the idea was quickly formulated and i guess really up the hill …

i have one issue up my neck.

i created two actions one is for NPC giving man options and listing it …that works …other action is for user responding to NPC …couse my story teller has vivid mind and text does seem to be bit long i decided to use a,b,c,d,e,f leters as topics to work on. but i dont know how to read those letters from user input and compare to possible answers in (abcdef)…in one case inform crashes in most cases it doesnt work correctly and in other cases it doesnt compile here is example what im trying to do

i have a table of

Table of SomeChat
Index	Options	Persona	PrintOut
1	{ 2, 3 }	NPC	"Hello there! "
2	{ 4 }	User	"I'd like a cappuccino, please."
3	{ 5 }	User	"Do you know what to do with a floppy?"
4	{ 6 }	NPC	"Ah, a cappuccino! Excellent choice."
5	{ 6 }	NPC	"A floppy, black like a perfect espresso."

Table of talks
Index	Persona	Tables	RanThrou	ActiveIndex	PrintOut
1		NPC	Table of SomeChat	0	1	"You realy shouldnt drink so much coffee"

then NPC part

Talking is action applying to one thing. Understand "talk to [person]" as talking. Carry out talking:
	Let Chat be a list of text; 
	Repeat with A running  from 1 to the number of rows in the Table of talks: 	
		if the Persona in row A of the Table of talks is noun:
			Now TalkingPartner is Persona in row A of the Table of talks;
			Now Command prompt is "Talking to [TalkingPartner] >";
			if  the RanThrou in row A of the Table of talks is 0:
				Let MyConvo be the tables in row A of the Table of talks;
				Let Y be ActiveIndex  in row A of the Table of talks;
				if the Persona in row Y of the MyConvo is noun:
					say "[the PrintOut in row Y of  MyConvo].[line break]";
					say "You can talk about following:[line break]";
					Now TalkOptions is 0; 
					Let UserOpt be the Options in row Y of the MyConvo;
					repeat with N running through the UserOpt:
						increment TalkOptions;
						say "     [the PrintOut in row N of  MyConvo].[line break]";
	Continue the action.

and user part

Optioning is action applying to one topic. Understand "[text]" as Optioning. Carry out Optioning:
	let TalkAnswers be { "a" , "b" , "c" , "d" , "e" };
	if Command prompt is "Talking to [TalkingPartner] >":
		Repeat with A running  from 1 to the number of rows in the Table of talks:
			if the Persona in row A of the Table of talks is TalkingPartner:
				Let MyConvo be the tables in row A of the Table of talks;
				Let Y be ActiveIndex  in row A of the Table of talks;
				Let UserOpt be the Options in row Y of the MyConvo;
				now TalkResponse is 0;
				let foundMe be false;
				Repeat with U running through TalkAnswers:
					if foundMe is false:
						increment TalkResponse;
						if topic does match U:
							now foundMe is true;
				if foundMe is true:
					say "[TalkResponse]";
					now  ActiveIndex in row A of the Table of talks is  entry TalkResponse  of UserOpt;
					try talking TalkingPartner;
	continue the action.

problem is in if topic does match U: im trying to do it as generic as possible since i just want to produce tables of convo later with main convo logic working …i would appreciate if someone can find a bug

I don’t have time to check your entire code right now, but this is not valid syntax in any case.

try “if topic matches U”

i did
topic matches u
topic is u
player command is u <–return ide error
topic is “[u]”

and changing order of topic and u.
in most cases it just goes thru anything and expresion is always true

Ok, sorry. Like I said, I didn’t go through your whole code. I thought you were using a variable called “topic”, but it looks like you’re using the text entered during the “talking” action.

In that case, it’s the “topic understood

1 Like

i in case player’s command prompt or using topic understood and comparing it to list of text i get following error:

I added some necessary variables in order to compile the code you provided above:

The Lab is a room.

NPC is a person in the Lab.
User is a person in the Lab.

TalkingPartner is a person which varies.
TalkOptions is a number which varies.
TalkResponse is a number which varies.

(I don’t know whether that’s how it’s in your code, that’s just what I added to have a compilable version in principle.)

I got the same error as in your screenshot.

The problem still seems to be in the line:

if topic understood matches U:

That line tries to compare the “topic understood”, which is internally a so-called “snippet” (basically Inform’s term for something which the player typed in), to a string/text (since U is an entry in the TalkAnswers list, like “b”).

Normally, the syntax “(snippet) matches (...)” expects a so-called “topic” in the second place (yes, the nomenclature is confusing here, unfortunately), not a string/text. This expectation isn’t fulfilled here, and that seems to be the source of the error – although I think the compiler normally catches that and gives a better error message, so that’s strange.

Anyway, if we replace that line with this one:

if topic understood exactly matches the text U:

… then Inform will know that we intend a comparison between a snippet and a text, and the code compiles.

However, there are still some issues remaining. For example, when the player types “d” during the conversation, then Inform will interpret that as the abbreviation for “down”, resulting in the response “You can’t go that way.”; same with “e” for “east”. And I ran into run-time problems due to looking up entries in table rows which don’t exist. I didn’t look at the rest of the code closely, just enough to find the problem discussed above.

I think it could be helpful to take a look at Michael Martin’s extensions “Reactable Quips” and “Quip-Based Conversation”. You could use those directly to get a menu-based conversation where the player types a number to select a conversation option, or if you want to roll your own system, you could take them as an example how to implement it.

hi
thank this indeed solves my compiler issue :slight_smile: thank you for head up about abreviation…i did try to work with numbers but i ran into problem that i wasn’t familiar with “topic” word and its use plus when using numbers i got compiler error that problem with number is that inform says something as its prohibited to compare with number as user can type 6 or “six” …it was all about this same line as i im strugling with. The rest of the code is ok only this one “if” line is realy a big big lunch i have to chew through. i would use numbers as they are more easy to use and i dont have to use list of text (“a”,“b”,“c”,“d”,“e”) but again this one “if” sentence is a problem… im kinda in a rush …so ill see if i will have real problem with abreviation and if i can supress it …code is now better designed not yet flowless as its work in progres …but ill get there… thank you very much for help… the variables you introduced are indeed missing in my post but glad you had no problem.

1 Like

Thank you all indded thank you very much…ive got it working with numbers :slight_smile: ahh the beauty :slight_smile: here is sample snippet

gameRes is number that varies.	
Gaming is action applying to number. understand "guess [number]" as gaming. Carry out gaming:
	let MyListOfWords be { "apple" , "brick" , "coolest" , "dungen" , "email" , "friend" };
	now gameRes is -1;
	if number understood is less than number of entries of MyListOfWords and number understood is greater than 0:
		now gameRes is number understood;
		say "[entry gameRes  of MyListOfWords]";
	Otherwise:
		say "Out of bounds";
	continue the action.
1 Like

Good job!

Just one small thing; you have:

if number understood is less than number of entries of MyListOfWords (and ...)

But since Inform, unlike many other programming languages which start from 0, starts counting list entries from 1, the number of the last entry is equal to the length of the list; so in the example, “friend” is entry 6, and the game should allow “guess 6”.

So, that line should be:

if number understood <= number of entries of MyListOfWords (and ...)

or equivalently:

if number understood is at most number of entries of MyListOfWords (and ...)
1 Like

thank you :slight_smile:

1 Like