Help avoiding an infinite loop

So I’ve decided to continue working on the dialogue system tech demo I’ve been working on and have run into something I can’t quite wrap my head around. Pretty much what I want to have happen is that at certain points I would like the player to be able to either type an action or select that action from the dialogue menu like any other choice. I would like both of these to do the action first, and then carry out the action related to displaying the response text and all the other dialogue related things. I’ve already got it to work where the player could do one of these thing, either select by typing a number or by typing out the action but I would like the player to be able to do either. The problem I’ve run into is that if the player types in a number I then need to have that action call the action they are selecting, but if they type the action that action then needs to call the actions which selects which dialogue entry it is. Thus creating an infinite loop.

Here are the main two blocks of code which are causing the loop.

Before doing something other than choosing when the command prompt is "You respond>":
	[if the current action is listed in Available Actions:
		choose row with actions of current action in the current conversation table;
		try choosing label entry;
	otherwise:]
		say "[The Current Speaker] eagerly awaits your reply."

Carry out choosing a number(called the number chosen):
	choose row with label of the number chosen in the Current Conversation Table;
	if there is actions entry:
		try actions entry;
	say "[The Current Speaker] says, '[Response entry]'";
	say paragraph break;
	increase the selected entry by 1;
	now index is 0;
	if number of entries in available actions is greater than 0:
		remove entries 1 to number of entries in available actions from Available Actions;
	if there is next topic entry:
		now Current Conversation Table is next topic entry;
		repeat with i running from 1 to the number of rows in the Current Conversation Table:
			choose row i in Current Conversation Table;
			unless choice entry is "":
				increase index by 1;
				say "[bracket][index][close bracket]. [Choice entry]";
				say line break;
				now label entry is index;
				if there is actions entry:
					add actions entry to Available Actions;
	otherwise:
		now the current topic is "";
		now the current speaker is empty person;
		now the current conversation table is the table of blankness;
		now the command prompt is ">".
And this is the full code to understand how things work in context
Lab is a room. Gwen is a person. Gwen is here. An envelope is here.

Current Topic is a text that varies.
The index is a number that varies. Index is 0.
A person has a table name called Master Dialogue.
Current Conversation Table is a table name that varies. The Current Conversation Table is the Table of Blankness.
Current Speaker is a person that varies.
Available actions is a list of actions which varies.
An emotion is a kind of value. The emotions are Happy, Sad, Angry.
A person has an emotion called mood.

Empty person is a person.

Table of Blankness
E
a text

Table of Gwen's Dialogue Master
Conversation	Speech	Choice Table	Selected
"test"	"I am testing!"		Table of Gwen's Dialogue Test	0
"weather"	"It sure is weather outside!"	Table of Gwen's Dialogue Weather	0

Table of Gwen's Dialogue Test
Choice		Response	next topic	Selected 	Label	Actions
"Can you test the quanitity of choices you can provide the player?"	"Sure thing, let me show you!"	Table of Gwen's Dialogue Quantity	0	number	an action
"What can you tell me about the quality of the choices?"	"A whole lot I'm sure!"	Table of Gwen's Dialogue Quality	0	--	--

Table of Gwen's Dialogue Weather
Choice		Response	Selected 	next topic	Label	Actions
"Yep it sure is weather."	"Weather!"	0	a table name	number	an action
"What?"	"Huh?"	0	--	--	--

Table of Gwen's Dialogue Quantity
Choice		Response	Selected	next topic		label	Actions
"This choice doesn't have any follow up choices, so choosing this ends the conversation, this could be a goodbye or just a choice with a response from the character that doesn't merit more choices."	"Goodbye"	0	--	a number	--
"You can have as many of these dead end choices as you want."	"Goodbye"	0	--	--	--
"Otherwise a dialogue choice can lead to another dialogue choice."		"I can say my response to you and then allow you to continue the conversation with more choices, this is done by having another table where all of your response to what I say are listed, just like all of your previous choices were listed in a table associated with your first choice."	0	Table of Gwen's Dialogue Continued Quantity		--	--

Table of Gwen's Dialogue Continued Quantity
Choice		Response	Selected	next topic	label	Actions
"You can have as many diaogue choices as you want here's 10 just for show."		"This was obviously the best choice, I think thats all I have to say about quanitity though, feel free to ask me about Quality if you haven't already."	0	--	a number	an action
"1"		"You chose 1."	0	Table of Gwen's Dialogue Numbers	--	--
"2"		"You chose 2."	0	Table of Gwen's Dialogue Numbers	--	--
"3" 	"You chose 3."	0	Table of Gwen's Dialogue Numbers	--	--
"4"		"You chose 4."	0	Table of Gwen's Dialogue Numbers	--	--
"5"		"You chose 5."	0	Table of Gwen's Dialogue Numbers	--	--
"6"		"You chose 6."	0	Table of Gwen's Dialogue Numbers	--	--
"7"		"You chose 7."	0	Table of Gwen's Dialogue Numbers	--	--
"8"		"You chose 8."	0	Table of Gwen's Dialogue Numbers	--	--
"9"		"You chose 9."	0	Table of Gwen's Dialogue Numbers	--	--
"10"	"You chose 10."	0	Table of Gwen's Dialogue Numbers	--	--

Table of Gwen's Dialogue Numbers
Choice		Response		Selected		Next Topic		Label	Actions
"And 10 more choices! These could all be seperate choices in their own table but I just had all the choices lead to this one table to go easy on myself."	"That sure is a lot of choices!"	0	a table name	a number	an action
"1"		"You chose 1."	0	--	--	--
"2"		"You chose 2."	0	--	--	--
"3"		"You chose 3."	0	--	--	--
"4"		"You chose 4."	0	--	--	--
"5"		"You chose 5."	0	--	--	--
"6"		"You chose 6."	0 	--	--	--
"7" 	"You chose 7."	0	--	--	--
"8"		"You chose 8."	0	--	--	--
"9"		"You chose 9."	0	--	--	--
"10"	"You chose 10."	0	--	--	--


Table of Gwen's Dialogue Quality
Choice		Response	Selected	Next Topic	Label	Actions
"With this example I'll show how text can be looped."	"I'm looping."	0	Table of Gwen's Dialogue Quality	a number	an actions
"Continue to the next example."		"I was having fun with that! Fine, lets continue."	0	Table of Gwen's Dialogue Quality Continued	--	--

Table of Gwen's Dialogue Quality Continued
Choice		Response	Selected	Next Topic	Label	Actions
"The dialogue choices you make can be remembered both within and outside of dialogue, along with how many times you have chosen it."	"You've seen this response [the selected in row 1 of Table of Gwen's Dialogue Quality Continued][if the selected in row 1 of Table of Gwen's Dialogue Quality Continued is 1] time[otherwise] times[end if] before."	0	Table of Gwen's Dialogue Quality Continued 2	--	--

Table of Gwen's Dialogue Quality Continued 2
Choice		Response	Selected	Next Topic	Label	Actions
"[if the selected in row 1 of Table of Gwen's Dialogue Quality Continued 2 is greater than 1]And we can change this choice one final time.[otherwise if the selected in row 1 of Table of Gwen's Dialogue Quality Continued 2 is 1]This is still the same entry in the table but it now detects you've selected it more than once.[otherwise if the selected in row 2 of Table of Gwen's Dialogue Quality Continued 2 is greater than 0]Several conditions can be used to vary the text of a choice.[end if]"		"[if the selected in row 1 of Table of Gwen's Dialogue Quality Continued 2 is 0]Select this choice again to see it change.[otherwise if the selected in row 1 of Table of Gwen's Dialogue Quality Continued 2 is 1]Even the response can be changed with the same conditions.[otherwise if the selected in row 1 of Table of Gwen's Dialogue Quality Continued 2 is greater than 1]But that's all of the changes to the text I have, however I can now change the next topic entry of this choice so that instead of looping, it'll continue on to the next topic.[go to topic Table of Gwen's Dialogue Quality Continued 3  from row 1 of Table of Gwen's Dialogue Quality Continued 2][end if]"	0	Table of Gwen's Dialogue Quality Continued 2	a number	--
"[if the selected in row 2 of Table of Gwen's Dialogue Quality Continued 2 is 0]Choices can be hidden until certain  conditions are met, the order of hidden choices doesn't matter. The first choice of this table isn't available until you've selected this choice once.[Otherwise if the selected in row 2 of Table of Gwen's Dialogue Quality Continued 2 is 1]Conditions can also be used to hide choices."	"[if the selected in row 2 of Table of Gwen's Dialogue Quality Continued 2 is 0]This choice loops so you can select the now revealed choice to continue the demonstration.[Otherwise if the selected in row 2 of Table of Gwen's Dialogue Quality Continued 2 is 1]Now there will only be 1 choice again."	0	Table of Gwen's Dialogue Quality Continued 2	--	--

Table of Gwen's Dialogue Quality Continued 3
Choice		Response	Selected	Next Topic	Label	Actions
"That's all for now."	"If you think there's any sort of uses/mechanics that I haven't implemented feel free to let me know!"	0	A table name	a number	--
"[if the player carries the envelope][bracket]Show Gwen the envelope[close bracket]"		"[if the mood of gwen is Happy]I'm so happy![otherwise if the mood of gwen is Sad]I'm sad now.[otherwise if the mood of gwen is Angry]I'm so mad right now!"	0	--	--	showing envelope to Gwen		

To say go to topic (next - a table name) from row (# - a number) of (conversation - a table name):
	choose row # in the conversation;
	now next topic entry is next.

To say gwen emote:
	now the mood of gwen is a random emotion.
	
The Master Dialogue of Gwen is Table of Gwen's Dialogue Master.

Understand "[a number]" as choosing.

Choosing is an action applying to one number.

Before doing something other than choosing when the command prompt is "You respond>":
	if the current action is listed in Available Actions:
		choose row with actions of current action in the current conversation table;
		try choosing label entry;
	otherwise:
		say "[The Current Speaker] eagerly awaits your reply."
	
Check choosing a number when the current conversation table is the table of blankness:
	say "There is currently no one to respond to.";
	stop the action.

Check choosing a number less than 1:
	say "Natural numbers only";
	stop the action.

Check choosing a number greater than Index:
	say "Please choose from the choices available.";
	stop the action.

Carry out choosing a number(called the number chosen):
	choose row with label of the number chosen in the Current Conversation Table;
	if there is actions entry:
		try actions entry;
	say "[The Current Speaker] says, '[Response entry]'";
	say paragraph break;
	increase the selected entry by 1;
	now index is 0;
	if number of entries in available actions is greater than 0:
		remove entries 1 to number of entries in available actions from Available Actions;
	if there is next topic entry:
		now Current Conversation Table is next topic entry;
		repeat with i running from 1 to the number of rows in the Current Conversation Table:
			choose row i in Current Conversation Table;
			unless choice entry is "":
				increase index by 1;
				say "[bracket][index][close bracket]. [Choice entry]";
				say line break;
				now label entry is index;
				if there is actions entry:
					add actions entry to Available Actions;
	otherwise:
		now the current topic is "";
		now the current speaker is empty person;
		now the current conversation table is the table of blankness;
		now the command prompt is ">".

Starting conversation about is an action applying to one topic.

Understand "Start conversation about [text]" as starting conversation about.

Check an actor starting conversation about a topic:
	if "[the topic understood]" is not a conversation listed in the Master Dialogue of the actor:
		say "[The actor] has nothing to say about [the topic understood]";
		stop the action.

Carry out an actor starting conversation about a topic:
	now Current Speaker is the actor;
	now Current Topic is the topic understood;
	choose row with conversation of Current Topic in the Master Dialogue of Current Speaker;
	say "[Current Speaker] says, '[Speech entry]'";
	say paragraph break;
	now Current Conversation Table is Choice Table entry;
	repeat with i running from 1 to the number of rows in the Current Conversation Table:
		increase index by 1;
		choose row i in Current Conversation Table;
		say "[bracket][index][close bracket]. [Choice entry]";
		say line break;
		now label entry is index;
	now the command prompt is "You respond>".

Talking to is an action applying to one thing.

Understand "Talk to [someone]" as talking to.

Carry out Talking to Gwen:
	try Gwen Starting conversation about "test".

The block showing rule is not listed in any rulebook.

Carry out showing the envelope to gwen:
	say "Gwen takes the envelope and opens it, she quickly reads over it's contents and gasps.[gwen emote]".

I’ve been trying to parse your query, but it’s a bit too hard for me to understand. I guess the problem is your demo(s) don’t demonstrate the problem, or if they do, it’s not clear how to get in a situation where I could test the problem.

Separately, I can’t understand the problem in the abstract by reading your ‘So I’ve decided…’ paragraph on its own.

Ideally, when you want help investigating something like this, try to put all the needed code in one demo, and include a test command at its end that will run the commands needed to demonstrate the problem.

So in this source, your test line might be something like

Test me with "get envelope/talk to gwen/3" ... etc.

Then if I drop your code in Inform and type ‘test me’, it’ll run the commands needed to produce the infinite loop you want examined.

From my incomplete understand, though, I’m guessing that the solution to your problem might end up being something like creating dummy actions corresponding to the numeric choices (e.g. ‘Choosing the first option is an action applying to nothing. Choosing the second option is an action applying to nothing.’… or even just ‘Choosing an option is an action applying to… yada’) and firing them when the user enters numeric input, thus providing an alternate path for the input and avoiding an action calling itself. Of course I speak in vague terms because my understanding has been vague, and this may not be the solution at all :slight_smile:

-Wade

1 Like

I’m also having trouble following the problem, but I endorse the suggestion of creating another set of actions. I had to do this in order to solve a different problem, eg (slightly redacted).


Kicking is an action applying to one thing. Understand "kick [someone]" as kicking.
Punting is an action applying to one thing. Report punting (the NPC): say "You kick (the NPC's name) viciously in the right shin."

Carry out kicking someone:
	try punting the noun;
	try (the NPC) riposting;
	say "(the NPC) stands on one foot and bends to rub his shin with his free hand, looking up at you. (further text related to the cooldown)";

I did this in order to allow the description of the action, the description of the NPC’s response (riposting, an action I built elsewhere in the code), and the cooldown text to print in the correct order. But it seems like the general concept might also work for you.

Thank you @KitParsing and @severedhand. Sorry my post was confusing. I think you are both right in that the only real way I’ll be able to get around the infinite loop would be to have some third action handle it, however I’m unsure of how really I could go about this. I’m going to try exploring this idea a bit though I suspect I’ll just end up having to choose using only one of the ways I currently have set up. To clarify a little bit using your example kit, pretty much what I’m trying to do would be to have a Kick and Punt action which under certain circumstances has both actions fire at the same time but normally they do their own thing (so kicking isn’t just a synonym for punting). I’m not sure if that makes things clearer.

I think you just need to set up a binary flag to stop the loop. Something like the scheme here:

Choice_preprocessing is a truth state that varies. Choice_preprocessing is true.

Before doing something other than choosing when the command prompt is "You respond>" and choice_preprocessing is true:
          (etc.)

Carry out choosing a number (called the number chosen):
          now choice_preprocessing is false;
          (etc.)

After choosing a number:
          now choice_preprocessing is true;
          continue the action.