Table entries that result in a change or action?

Hey guys and/or girls,

sorry to bother you again

I’m trying to make a conversation puzzle that does stuff depending on what the player says to a character.

The hallway is a room. "hallway description."

A man named Nilson is here. Nilson is undescribed.
The description of Nilson is "[line break]You spot the half-empty bottle of Jim Bean tucked under his arm. He looks and smells like he hasn[apostrophe]t showered, shaved or changed his clothes in a while. Even in your line of work, you find it pretty hard not to sorry for the guy."
Nilson is carrying a bottle of Jim Bean.

Instead of taking the bottle of Jim Bean, say "[line break]Nilson turns away and sneers, 'This bottle is my only consolation and you try to take it away from me!? You[apostrophe]ve done enough to me already!'"

HallwayDoor is a closed door. HallwayDoor is west of the hallway and east of the entryway.
Before opening HallwayDoor:
	If blockhallwayexit is in the void: 
		say "[line break][one of]As you try to exit the premises, you are accosted by former client--what's his name? That[apostrophe]s right, Nilson. He is sobbing hysterically and muttering incoherent words under his breath. Must be repining over the case you just cracked where you caught his wife with a younger man. You sigh, 'Not another one. Why do these lunatics pay me to confirm their suspicions, only to deny it once I reveal it to them? It seems it[apostrophe]s always these pathetic business-types too.' He points at you with his crooked finger, and finally articulates a 'Y-y-you!'[or]Better deal with this guy first. He seems to be blocking your exit.[stopping]" instead.
	
Instead of asking Nilson to try doing something:
	repeat through Table of Nilson's Commentary:
		if player's command includes topic entry:
			say "[commentary entry][paragraph break]";
			try result entry;
			rule succeeds;
	say "[line break][one of]Nilson sobs[or]'Oh Lorraine! Why?'[purely at random]".

Instead of speech when the noun is Nilson:
	repeat through Table of Nilson's commentary:
		if the topic understood includes topic entry:
			say "[commentary entry][paragraph break]";
			try result entry;
			rule succeeds;
	say "[line break][one of]Nilson sobs[or]'Oh Lorraine! Why?'[purely at random]".

Table of Nilson's Commentary
topic	commentary	result	
"Lorraine"	"Oh Lorraine, why did she leave me?"	DealingWithNilson
"blah"	"blah blah blah blah."	screaming
"calm down"	"you calm down!"	screaming
"want"	"what do you want?"	screaming	
"okay/ok"	"you would say that wouldn[apostrophe]t you?"	screaming


[yelling/screaming]
Understand "scream" as screaming.
Understand "yell" as screaming.
Screaming is an action applying to nothing.
Report screaming: say "You yell - '[bold type]Aarrggghhh!!![roman type]'[line break]".

Understand "DealWithNilson" as DealingWithNilson.
DealingWithNilson is an action applying to nothing;
Carry out DealingWithNilson:
		remove blockhallwayexit from play.

The void is a room. 
In the void is an object called blockhallwayexit.

I’m sure there are better ways to achieve this, but Blockhallwayexit is my convoluted n00bish way of trying to get it so you cannot leave until you say the right thing to Nilson. Bear with the crappy dialogue. It’s just filler right now. But I’m trying to get it to remove the blockhallwayexit object from play if the correct thing is said or mentioned. The try screaming works, but inform does not recognize DealingWithNilson. I tried using a phrase instead of an action, but no dice.

1.) My first question is, how can I make it so mentioning the right thing removes blockhallwayexit?

2.) second, I noticed that “includes” only works with like the first three words. Is there a way to detect if the player mentions the topic entry at all? It does not recognize, “You need to calm down,” but it does recognize “calm down.”

3.) I asked this earlier. Is there a way I can make it so that I don’t have to say “Nilson, blah blah blah” in order to respond to Nilson?

I really appreciate your help.

Inform 7 writing conventions differ a bit from most (or any other) programming language. In this case you’re tripped by a habit to avoid blank spaces.
Action names should contain some word ending in -ing. Rename the DealingWithNilson action; call it “dealing with Nilson” and your halfway there.
For the same reason “speaking” would a better choice than “speech”. I’ve used “answering something that”, since that is an action already defined in the Standard Rules.
Lastly, “A man named Nilson is here” creates a thing called “man named Nilson”. You want “A man called Nilson is here”.[code]The hallway is a room. “hallway description.”

A man called Nilson is here. Nilson is undescribed.

HallwayDoor is a closed door. HallwayDoor is west of the hallway and east of the entryway.

Before opening HallwayDoor:
If blockhallwayexit is in the void:
say “[line break][one of]As you try to exit the premises, you are accosted by former client–what’s his name? That[apostrophe]s right, Nilson. He is sobbing hysterically and muttering incoherent words under his breath. Must be repining over the case you just cracked where you caught his wife with a younger man. You sigh, ‘Not another one. Why do these lunatics pay me to confirm their suspicions, only to deny it once I reveal it to them? It seems it[apostrophe]s always these pathetic business-types too.’ He points at you with his crooked finger, and finally articulates a ‘Y-y-you!’[or]Better deal with this guy first. He seems to be blocking your exit.[stopping]” instead.

Instead of answering Nilson that:
repeat through Table of Nilson’s commentary:
if the topic understood includes topic entry:
say “[commentary entry][paragraph break]”;
try result entry;
rule succeeds;
say “[line break][one of]Nilson sobs[or]‘Oh Lorraine! Why?’[purely at random]”.

Table of Nilson’s Commentary
topic commentary result
“Lorraine” “Oh Lorraine, why did she leave me?” Dealing With Nilson
“blah” “blah blah blah blah.” screaming
“calm down” “you calm down!” screaming
“want” “what do you want?” screaming
“okay/ok” “you would say that wouldn[apostrophe]t you?” screaming

Screaming is an action applying to nothing.
Report screaming: say “You yell - ‘[bold type]Aarrggghhh!!![roman type]’[line break]”.

Dealing With Nilson is an action applying to nothing.
Carry out Dealing With Nilson:
remove blockhallwayexit from play.

The void is a room.
In the void is an object called blockhallwayexit.

test me with “w / w / Nilson, please, you need to calm down / Nilson, calm down!!! / w / Nilson, what about Lorraine? / w”[/code]

Oooh! This actually is directly related to my next question. Can I threadjack? :slight_smile: I’m trying to use a table to determine the result of an action as well. In my case, I’m trying to have a microwave oven that, when used on various objects, performs various actions (basically, it sets properties on each). What I’m confused about is how to pass ‘the noun’ through from the microwaving activity to the activity triggered by the table. Here’s my code:

[microwaving]
Microwaving is an action applying to one thing.
Understand "microwave [something]" as microwaving.
Understand "cook [something]" as microwaving.
Understand "heat [something]" as microwaving.
Understand "reheat [something]" as microwaving.

Check microwaving:
	Unless the microwave oven is in the location, say "How do you propose to do that?" instead;
	Unless the microwave is empty:
		Unless the noun is in the microwave, say "There's no room in the microwave." instead.
	
Carry out microwaving:
	unless the noun is in the microwave oven:
		try opening the microwave oven;
		try inserting the noun into the microwave oven;
		try closing the microwave oven;
	say "The oven hums loudly for a few moments, then [italic type]BING![roman type] It stops."

After microwaving:
	repeat through Table of Microwaving:
		if the noun is item entry:
			try result entry on the noun;
			rule succeeds;
	say "DONE".


Table of Microwaving
item	result	description
coffee	Heating	"The coffee is now steaming slightly."


[Microwave result actions]
[heating]
Heating is an action applying to one thing.

Carry out heating:
	now the noun is hot;
	say "Now [the noun] is hot!";

…so in my example, I want to try carrying out the ‘heating’ action if it’s appropriate for the object (in my example, coffee). I have multiple things that might be heated, so I’d like to use a single action for them. The line that doesn’t work is:

try result entry on the noun;

Do I have my syntax wrong? Is that sequence even possible? If so how? I might have a bunch of different items that share the ‘heating’ action, so I can’t just hardcode what gets heated into the ‘heating’ action (I’d have to write a bunch of different, specific heating actions for each item).

(or, of course, am I just going about this whole microwave thing wrong… :slight_smile:

Thanks!

Three things. First, to edit a stored action you need Include Editable Stored Actions by Ron Newcomb.
Once you have that, you can writeAfter microwaving: repeat through Table of Microwaving: if the noun is item entry: let the attempt be the result entry; now the noun part of the attempt is the noun; try the attempt; say "DONE."
But you’ll also need to alter the actor part of the attempt or else to change your action declaration to Heating is an action applying to one visible thing. so that the player can heat the coffee despite not being able to reach it.

Brilliant. Works a treat, thanks!

It seems to me that instead of using Editable Stored Actions you might just want to put the whole stored action in the table column. So instead of having the result entry for coffee be “heating” (or “the heating action”), just make it “the action of heating the coffee”; since you’ll only be in that row when the noun is the coffee, you don’t lose any flexibility by coding “the coffee” into the row. (In fact, you might gain a bit of flexibility, since you can make it so that if you microwave the envelope the result is “the action of melting the seal” which is part of the envelope, if that’s useful.)

What EmacsUser says about the scope still holds, though, I think. If I’m not mistaken, when you try the stored action, what’s happening is that the game effectively has the player try the stored action, which might lead to issues. One workaround (as EmacsU suggests) is to redirect these actions so that a virtual actor inside the microwave does them, and make sure the rules for the virtual actor work the way you want the actions to work. You can do this with stored actions too; if the actor is “the ghost,” the stored action would be something like “the action of the ghost trying heating the coffee.”

Stored actions are in 10.20 of the documentation, by the way.

Thanks everyone. I encourage thread-jacking, since I’m learning too. Pretty nifty.

'nother n00b question: I thought you needed to download extensions. Are those built-in? I noticed something that said “installed extensions” in the documentation.

I would still like to know how to allow players to speak to people without having to type: “[person’s name], blah blah blah.” “Ex. 9 - Sybil 2” offers one way, but is there a way to do it if you don’t want to create new actions for each reply? I’m looking all over the place with no results. I would be ever-so-grateful if someone has an answer.

matt w: Ooh! I’ll try that too! re: having players try actions - yeah, I realized that might be an issue, so I’m doing everything from the ‘After microwaving’ block so the player doesn’t have time to get out of the room.

My current problem is that my table tests fails if I have an example of a kind instead of a unique object. How can I determine the noun’s kind so I can run that thru a different table?

More info: When I use the above method, but the object in question is one of a kind and not a specifically defined object (i.e. ‘a fleeb is a kind of thing. There are 10 fleebs in the backpack.’ and the object is a fleeb) the table lookup fails because it says the thing in column 1 doesn’t exist. I’m guessing that’s because a ‘fleeb’ is not a ‘noun’ but a ‘kind’ - but I don’t know how to search for the kind.

Phrog: I had to download the extension first and install it, yes.

There are a handful of extensions that come pre-packaged with Inform, such as Emily Short’s Basic Help Menu, but there are far more to be downloaded from the site. You can see all the installations you currently have installed by clicking “Installed Extensions” in the documentation table of contents. (Note that once an extension is installed, you still need to “include” it in any given project for it to be part of that project.)

No one has yet jumped in to say that you can easily do this, so let me say: I don’t think you can do this exact thing easily. One problem is that there’s no such thing as the kind of an object; many objects will have several (if a florb is a kind of container, then any given florb has kinds florb, container, thing, and object, I think). Another thing is that you can’t have a table column that mixes things and kinds; every entry in a column has to be of the same type, so you can’t have a column that contains both “coffee” (a thing) and “container” (a kind); Inform won’t know what to do with it.

One thing that you might be able to do is make two tables, the Table of Specific Microwaving with a column of things and the Table of Generic Microwaving with a column of kinds. Then you could check things to see if they’re listed in the Specific table first, and then to see if they belong to a kind listed in the Generic table. But you might not even be able to get a table with a kind column to work, and if you can I’m not sure how to check whether the noun belongs to that kind. (There’s some discussion here.)

matt w: Gargh. I was afraid of that. I’d planned to have two tables, one of things and one of kinds, and if none of the things matched then run through kinds - but, as you say, there doesn’t seem to be a way to table match on the kind of an object. This is…discouraging. I don’t want to lose my whole microwave puzzle, but…hmmm. Thanks for the pointer.

So I sort of managed to do what I wanted to do, using what feels like a vicious hack. :slight_smile: I have a lucky case because all the items I’m checking have a common word ending their name - they’re all types of chips, so ‘broadcast chip’ and ‘memory chip’ and so forth, but I think this technique might be extendable.

Instead of trying to match the kind of the noun to something in the table, I see if the printed name of the noun matches some text in the ‘kind’ column - in my case ‘chip’. This seems to work fine:

A broadcast chip is a kind of thing.  A broadcast chip is usually portable.  A broadcast chip can be working or fried. A broadcast chip is usually working. A broadcast chip is tiny.  The description of a broadcast chip is "This is a broadcast chip - a small solid-state radio about the size of a coin.  These can be found in most portable electronics these days.  Usually powered by small batteries in phones or car keys, these generally have a range of a few meters.  There are leads on the chip for connecting a data source and a power source.[if fried]  This chip is blackened and scorched; the magic smoke appears to have been released."

repeat through Table of Microwaving Kinds:
	if the printed name of the noun matches the text "[the kind entry]":
		let the attempt be the result entry;
		now the noun part of the attempt is the noun;
		try the attempt;
		say "[the description entry][line break]";
		break;

Table of Microwaving Kinds
kind	result	description
"chip"	the action of frying	"There is a sizzling noise. The chip is now scorched and smoking slightly."

Note that I’m using Editable Stored Actions by Ron Newcomb, as suggested - hence that ‘now the noun part of the attempt is the noun’ which saves me having to have a separate rule in the table for each type of chip and trying to construct a properly specific reference to them for the attempt.

I really should put in a test to make sure the attempt works before saying the result description. /me puts on list of Things To Do (which is still in the ‘growing’ phase for this project).

Woohoo!

Excellent!

One thing I’d forgotten to mention was that if you were going to do the kind description, you’d definitely need to return to Editable Stored Actions, but you already seem to have figured that out.

Anyway, if you can’t rely on “chip” appearing in everything, one thing you could do is giving objects a text property that you can match against the Table of Microwaving Kinds. So you could say

A thing has some text called the microwave name. The microwave name of a broadcast chip is usually "chip".

And then check for the microwave name of the thing in the Table of Microwaving Kinds. Then you wouldn’t be dependent on all your chips having “chip” in their name.

Belatedly, the code in the thread that matt w linked to does let you match by kind as long as you are dealing with objects under Glulx:[spoiler][code]Include Editable Stored Actions by Ron Newcomb.

Chapter “Object Types” (for Glulx only)

Include (-
[ convertPropRoutineToClass routine result;
@linearsearch OC__Cl 4 routine 1 (-1) 0 0 result;
return (result+5)–>0;
];
-) after “Definitions.i6t”.

An object type is a kind of value. An object type is an invalid object type. [This second sentence makes it possible to return types from phrases.]
To decide what object type is the (K - a description of a value of kind K) type: (- convertPropRoutineToClass({K}) -).
To decide what object type is the type of (O - an object): (- ({O}.2) -).
To repeat with (I - a nonexisting object type variable) running through object types begin – end: (- for({I}=K0_kind–>6:{I}:{I}={I}–>6) -).
To decide whether (O - an object) is of type (T - an object type): (- ({O} ofclass {T}) -).
To decide whether (O - an object) is of type (K - a description of a value of kind K):
decide on whether or not O is of type the K type.
To say (T - an object type): (- print (I7_Kind_Name){T}; -).

Chapter “Demo”

A thing can be tiny. A thing can be hot.
A broadcast chip is a kind of thing. A broadcast chip is usually portable. A broadcast chip can be working or fried. A broadcast chip is usually working. A broadcast chip is tiny. The description of a broadcast chip is “This is a broadcast chip - a small solid-state radio about the size of a coin. These can be found in most portable electronics these days. Usually powered by small batteries in phones or car keys, these generally have a range of a few meters. There are leads on the chip for connecting a data source and a power source.[if fried] This chip is blackened and scorched; the magic smoke appears to have been released.”

There is a room.
Here is a closed openable transparent fixed in place container called the microwave oven.
The player carries a broadcast chip called the green chip.
The player carries a broadcast chip called the red chip.
The player carries some coffee.

Definition: a container is nonempty rather than empty if it encloses something.

Microwaving is an action applying to one thing.
Understand “microwave [something]” as microwaving.
Understand “cook [something]” as microwaving.
Understand “heat [something]” as microwaving.
Understand “reheat [something]” as microwaving.

Check microwaving:
Unless the microwave oven is in the location, say “How do you propose to do that?” instead;
Unless the microwave is empty:
Unless the noun is in the microwave, say “There’s no room in the microwave.” instead.

Carry out microwaving:
unless the noun is in the microwave oven:
try opening the microwave oven;
try inserting the noun into the microwave oven;
try closing the microwave oven;
say “The oven hums loudly for a few moments, then [italic type]BING![roman type] It stops.”

After microwaving:
repeat through Table of Specific Microwaving:
if the noun is the item entry:
try the result entry;
rule succeeds;
repeat through Table of Generic Microwaving:
if “[the type of the noun]” exactly matches the text the kind entry:
let the attempt be the result entry;
now the noun part of the attempt is the noun;
try the attempt;
rule succeeds;
say “DONE”.

Table of Specific Microwaving
item result description
coffee the action of heating the coffee “The coffee is now steaming slightly.”

Table of Generic Microwaving
kind result
“broadcast chip” the action of frying

Heating is an action applying to one visible thing.

Carry out heating:
now the noun is hot.

Report heating:
say “Now [the noun] is hot!”

Frying is an action applying to one visible thing.

Carry out frying:
now the noun is fried.

Report frying:
say “There is a sizzling noise. The chip is now scorched and smoking slightly.”[/code][/spoiler]

(There is one tricky bit: using exactly matches the text'' instead ofis.’’ That’s because there are actually two copies of the text “broadcast chip” floating around—one for the kind and one for the table—and Inform considers them to be different. But since they have the same contents, a matching comparison works. See WI 19.5.)

Edit: Or see what matt w just posted, which is an equally viable approach.

There may be an extension that does this better, but here goes:

You want HOW DO YOU DO to be parsed like ABURTHNOT, HOW DO YOU DO.
HOW DO YOU DO normally triggers a command parser error (viz. ‘the not a verb I recognise error’), and ABURTHNOT, HOW DO YOU DO would normally be parsed as ANSWER ABURTHNOT THAT HOW DO YOU DO.
So, we need to suppress the command parser error for HOW DO YOU DO and make the command trigger the ‘answering it that’ action (with HOW DO YOU DO for topic and Aburthnot for noun).
That is, instead of printing a parser error, the game should guess whom the player addresses, change the player’s command accordingly, and try to make sense anew of the revised command.

First make a variable to store the game’s guess at whom the player is addressing.

The addressee is a thing that varies.

Whom is the player likely to address?
If the player starts talking to a person, he is likely to want to keep talking to the same person, unless he explicitly turns to anyone else. That is, if the player has typed ASK ABURTHNOT ABOUT CONTRABAND, it is likely that a following command that the game wouldn’t understand, such as WHAT ABOUT THE WHISKY THEN, will be directed to Aburthnot as well.

Before answering something that: now the addressee is the noun. Before telling something about: now the addressee is the noun. Before asking something about: now the addressee is the noun. Before asking something for: now the addressee is the noun. Before asking something to try doing something: now the addressee is the person asked.
Further, we can assume that the player would address only people other than himself/herself and that are visible to him/her.

[code]Definition: a person is another if he is not the player.

Before reading a command when another person (called the audience) is visible: if the addressee is yourself or the adressee is not visible, now the addressee is the audience.[/code]
That will pick a new potential addressee from the people present, unless the former addressee is still present.

Then we want to replace the ‘not a verb I recognise error’ with an ‘answering it that’ action.

For printing a parser error when the latest parser error is the not a verb I recognise error: let T be indexed text; let T be the player's command; change the text of the player's command to "[addressee], [T]".

I don’t know of an Inform 7 way to send the player’s command back to the parser at this stage in the parsing process. But it can be done by adding a line to one of the Inform 6 templates that Inform 7 uses.

[rant=code][code]Include (-
! If the player was the actor (eg, in “take dfghh”) the error must be printed,
! and fresh input called for. In three cases the oops word must be jiggled.

if ((etype ofclass Routine) || (etype ofclass String)) {
	if (ParserError(etype) ~= 0) jump ReType;
} else {
	if (verb_wordnum == 0 && etype == CANTSEE_PE) etype = VERB_PE;
	players_command = 100 + WordCount(); ! The snippet variable ``player's command''
	BeginActivity(PRINTING_A_PARSER_ERROR_ACT);
	if (ForActivity(PRINTING_A_PARSER_ERROR_ACT)) jump SkipParserError;
}
pronoun_word = pronoun__word; pronoun_obj = pronoun__obj;

if (etype == STUCK_PE) {    L__M(##Miscellany, 27); oops_from = 1; }
if (etype == UPTO_PE) {     L__M(##Miscellany, 28);
	for (m=0 : m<32 : m++) pattern-->m = pattern2-->m;
	pcount = pcount2; PrintCommand(0); L__M(##Miscellany, 56);
}
if (etype == NUMBER_PE)     L__M(##Miscellany, 29);
if (etype == CANTSEE_PE) {  L__M(##Miscellany, 30); oops_from=saved_oops; }
if (etype == TOOLIT_PE)     L__M(##Miscellany, 31);
if (etype == NOTHELD_PE) {  L__M(##Miscellany, 32); oops_from=saved_oops; }
if (etype == MULTI_PE)      L__M(##Miscellany, 33);
if (etype == MMULTI_PE)     L__M(##Miscellany, 34);
if (etype == VAGUE_PE)      L__M(##Miscellany, 35);
if (etype == EXCEPT_PE)     L__M(##Miscellany, 36);
if (etype == ANIMA_PE)      L__M(##Miscellany, 37);
if (etype == VERB_PE)       L__M(##Miscellany, 38);
if (etype == SCENERY_PE)    L__M(##Miscellany, 39);
if (etype == ITGONE_PE) {
	if (pronoun_obj == NULL)
							L__M(##Miscellany, 35);
	else                    L__M(##Miscellany, 40);
}
if (etype == JUNKAFTER_PE)  L__M(##Miscellany, 41);
if (etype == TOOFEW_PE)     L__M(##Miscellany, 42, multi_had);
if (etype == NOTHING_PE) {
	if (parser_results-->ACTION_PRES == ##Remove &&
		parser_results-->INP2_PRES ofclass Object) {
		noun = parser_results-->INP2_PRES; ! ensure valid for messages
		if (noun has animate) L__M(##Take, 6, noun);
		else if (noun hasnt container or supporter) L__M(##Insert, 2, noun);
		else if (noun has container && noun hasnt open) L__M(##Take, 9, noun);
		else if (children(noun)==0) L__M(##Search, 6, noun);
		else parser_results-->ACTION_PRES = 0;
		}
	if (parser_results-->ACTION_PRES ~= ##Remove) {
		if (multi_wanted==100)  L__M(##Miscellany, 43);
		else                    L__M(##Miscellany, 44);
	}
}
if (etype == ASKSCOPE_PE) {
	scope_stage = 3;
	if (indirect(scope_error) == -1) {
		best_etype = nextbest_etype;
		if (~~((etype ofclass Routine) || (etype ofclass String)))
			EndActivity(PRINTING_A_PARSER_ERROR_ACT);
		jump GiveError;
	}
}
if (etype == NOTINCONTEXT_PE) L__M(##Miscellany, 73);

.SkipParserError;
if ((etype ofclass Routine) || (etype ofclass String)) jump ReType;
if (etype == VERB_PE) jump ReParse; !### Adding this line ###
say__p = 1;
EndActivity(PRINTING_A_PARSER_ERROR_ACT);

-) instead of “Parser Letter I” in “Parser.i6t”.
[/code][/rant]

Then we can customize responses with after (or instead) rules

After answering Lovejoy that "how do you do": say "'How do you do, sir?' Lovejoy replies." After answering Aburthnot that "how do you do": say "Colonel Aburthnot but snorts in contempt."
(The rule ‘After answering Igbut that “how do you do?”’ won’t compile. The compiler doesn’t allow question or exclamation marks in text like that. So, if the player uses a question mark here, we can’t write a rule for his/her command. The best solution is probably to include the built-in extension Punctuation Removal by Emily Short and use it to remove exclamation and question marks from the player’s command before parsing it.)

Of course, the above code may or may not have any kind of unforeseen effects.

Felix, can you explain a little more about the I6 inclusion? That looks like it might be very useful in something else I was fiddling around with, where I learned that you can’t just trigger the parse command rule anytime you want.

In this case, though, I think trying to work through the “not a verb I recognise” error may be swatting a fly with a howitzer. Can’t we do this?

[code]Talking to the air is an action applying to one topic.
Understand “[text]” as talking to the air when the addressee is not the player and the addressee is visible.

Instead of talking to the air: try answering the addressee that the topic understood.[/code]

ETA: A side effect seems to be that when the addressee isn’t present, the “That’s not a verb I recognise” error gets replaced with “I didn’t understand that sentence.”

I tried that “[text]” approach at first. I can’t remember why I didn’t continue down that road. Probably I just made some stupid mistake and jumped to the conclusion it wouldn’t work. (Or maybe I was afraid that “[text]” would match too indiscriminately – which it doesn’t seem to do.)

“Jump” is I6 for “goto”.
The line

if (etype == VERB_PE) jump ReParse; 

means

if the latest parser error is the not verb I understand error jump/goto the label ReParse.

When the condition is true, the execution of the ongoing I6 routine jumps to and continues from a point earlier or later in that same routine marked “.ReParse;”. The parser uses this a couple of times (after OOPS and AGAIN I think). It resumes parsing immediately after the printing a command activity. (“jump ReType;” takes you to immediately before the printing a command activity, and there’s also an “AlmostReParse” label located a little later, which is apparently used when the actor is not the player.)

Thanks! That’s extremely helpful; if I’m doing any of these crazy parser hacks I’m probably going to use Ron Newcomb’s I7 Parser, and I think I can work out how to translate your thing into the I7 Parser if needs be.

I thought that my approach to the answering issue might preempt all parser errors, but it doesn’t seem to. Which means that if you want to say “i love you” to an NPC, you have to use their name or you’ll get an “I only understood you as far as wanting to take inventory” error. [It also probably means that my approach won’t introduce any extra hiccups over and above turning “that’s not a verb I recognize” into “I didn’t understand that sentence.”]

Felix, thank you soooooo much!

Unfortunately, this weekend will be reserved for thesis work (grad school, yay!)

But I will try this out some time next week and see if it works.

Just following through. Felix’s solution works really well. There were a few minor kinks. Nothing serious.

For whatever reason, Inform 7 is not liking my use of the word “or.” I just fixed it by writing a little extra code.

[code]
Before reading a command when another person (called the audience) is visible:
if the addressee is yourself:
now the addressee is the audience.

Before reading a command when another person (called the audience) is visible:
if the addressee is not visible:
now the addressee is the audience.[/code]

I sooo wish that or would work. It would have saved me so much unnecessary code. I’m still used to Java (not that I was any better with Java either, but it was a bit more straightforward. But I guess that’s the price you pay for a code that virtually looks like the English language).

The only other minor issue is if you have two people. Like the character has a dog that follows him around, so if I want to address someone other than the dog, i still have to use the NPC’s name. If I do a little trixy coding, I could make it so it prioritizes other NPCs over the dog. I could probably fix this with something along the lines of (it’ll take a bit of n00b-programmer thinking on my part):

Definition: a person is notcanine if he is not the dog.

[some condition that allows me check if another notcanine person is in the area, blah blah blah:]	
Before reading a command when another person (called the audience) is visible:
	if the addressee is the dog:
		now the addressee is the audience.

Also if I say “shut up” it’ll think I’m trying to shut a thing called an up. But that’s what the “instead” is for.

The program is so much more simple now. Could not have done it without you. Thanks again.