Bug? Topic-based actions not parsed if they share a verb word with another action

I was helping someone else with a project of theirs, and they ran into an issue that seems worth sharing. They had specified two actions and their associated grammars:

Understand "where is" or "which way is/to" or "which way is it to" or "how do/can I get to" or "which way do/can I go to get to" or "which way is it to get to" or "how do/can I get/go from here to" or "how do/can I get/go to" or "i want to go to" or "how to get to" as "[direction-asking preamble]".

Asking which way is an action applying to one thing. Understand "[direction-asking preamble] [room]" or "[direction-asking preamble] [room] from here" as asking which way. 
...
Asking what rooms is an action applying to nothing. Understand "rooms" or "places" or "where can I go" as asking what rooms.

The issue being experienced was that >WHERE IS LIBRARY (for example) would respond with a didn’t understand parser error, despite the fact that this wording was covered by the “[direction-asking preamble]”. Use of >TRACE showed that only the grammar line for the asking what rooms action was being evaluated.

Looking at the generated I6 code, the following could be seen:

Verb 'no.verb'
    * GPR_Line_94 noun=Noun_Filter_4  -> A78_asking_which_way
    * GPR_Line_94 noun=Noun_Filter_5 'from' 'here'  -> A78_asking_which_way
;
Verb 'where'
    * 'can' 'i//' 'go'  -> A80_asking_what_rooms
;

GPR_Line_94 is the routine token generated for the direction-asking preamble topic. What’s going on is that the parser is treating 'where' as a verb word but the I7 compiler didn’t take note that 'where' is also used by the direction-asking preamble topic, so when the one grammar line associated with that verb word fails, the parser decides that parsing has failed.

The short-term fix is to separate out the use of “where” for the asking which way action:

Understand "which way is/to" or ... as "[direction-asking preamble]".

Understand "where is [room]" as asking which way.

This way the I6 layer includes a grammar line for the asking which way action associated with 'where':

Verb 'where'
    * 'is' noun=Noun_Filter_6  -> A78_asking_which_way
    * 'can' 'i//' 'go'  -> A80_asking_what_rooms
;

However, it occurs to me that perhaps the parser behavior should be to try any grammar lines that begin with a routine token after running out of lines tied to specific verb words, since there is no way for the parser to know what words might be recognized by any particular GPR token.

Perhaps this issue has already been flagged – it’s the kind of thing that I would historically have researched on the Mantis site. I’m posting here so that it doesn’t get lost (or so that someone can explain why current parser behavior is preferable).

1 Like

I suspect that it is in recognition of this potential issue that the compiler formally disallows simple regex alternative syntax as the first word of grammar lines- e.g.

Understand "employ/deploy/utilise/use [something]" as using.

is rejected with an admonition not to do this sort of thing, although the functionally equivalent

Understand "employ/deploy/utilise/use" as "[utilising]".
Understand "[utilising] [something]" as using.

compiles as a (probably deprecated) workaround that returns GPR_PREPOSITION as the token type for the initial token, rather than a verb. These grammar lines are scanned by the parser with the substituted dummy verb of ‘no.verb’ only when it can find no valid verb in the initial word position of the player’s command, ‘no.verb’ being only made available to the parser by the compiler when it has encountered an ‘Understand…’ action declaration beginning with a token in the source.

As an aside, this mechanism exposes another bug, due to setting the I6 variable verb_wordnum to 0 when the verb is ‘no.verb’- this messes up the automatic diversion of commands such as ‘Darcy, hello’ to the ‘Answering it that’ action. If you have the stomach for it, read on…

If the parser is unable to interpret the first word of a command as a verb word in the dictionary, it calls the routine UnknownVerb, which has the opportunity to help the parser out by supplying a verb word for the parser to work with.
The I7 compiler normally generates a pair of UnknownVerb routines with a hard-coded directive for the I6 compiler to use one or the other according to whether I7 has detected any grammar line declarations that don’t start with a dictionary verb word. In the latter case, UnknownVerb sets the verb_wordnum to 0 and returns the untypeable verb ‘no.verb’ as the verb, which allows the parser to go on to consider grammar lines matching against ‘no.verb’. In the default case, where every grammar line declaration begins with a dictionary verb word, UnknownVerb just returns false and the parser does not go on to consider grammar lines.

#IFTRUE (1 == 1);
[ UnknownVerb; verb_wordnum = 0; return ‘no.verb’; ];
[ PrintVerb v;
if (v == ‘no.verb’) { print “do something to”; rtrue; }
rfalse;
];
#Ifnot;
[ UnknownVerb; rfalse; ]; [ PrintVerb v; rfalse; ];
#ENDIF;

In either case, if the player’s command starts by addressing a speakable object with, for example ‘Mr Darcy, …’ and no grammar lines match the text after the comma, the remainder of the command after the comma is considered to be an unparsed conversational topic and an ##Answer action generated, with the addressee as the ‘noun’ and the topic stored as a snippet in ‘second’.
This fails in the case where verb_wordnum has been set to 0, in UnknownVerb, because verb_wordnum is used by the parser in generating the ##Answer action to determine the start and length of the snippet (it ends up being (100*verb_wordnum) + (numwords-verb_wordnum+1). So for example, for ‘Darcy, hello’ where verb_wordnum should be 3 and the snippet should be 301, it is stored as 4. Obviously this will cause any code dependent on this snippet to fail, often with a program error because a snippet <100 suggests the first word is the (non-existent) 0th word of the player’s command and this leads to attempts to read below the lower bounds of the parse array.

Symptoms:
The fault can be easily demonstrated by declaring a grammar line for an action having a token as its initial word, compiling, invoking actions reporting with the ‘actions’ command, then inputting a command in the form ‘somebody, …’ . A programming error will be reported due to an out-of-bounds array reference.

In source:

Utilising is an action applying to one visible thing.
Understand “[utilise] [something]” as utilising.
Understand “use/employ/deploy” as “[utilise]”.

In play:

actions
Actions listing on.

darcy, hello
[answering Mr Darcy that "
[** Programming error: tried to read from -->-1 in the array “parse”, which has entries 0 up to 60 **]
darcy , hello"]

Any code trying to reference ‘the topic understood’ for this action, or to ‘say’ the action, will similarly run into trouble.

Obviously, the simple way to avoid the problem is by not declaring grammar lines with a token as their first word. As far as I can see, it can be fixed only by making a couple of tweaks to the parser…

caveat scriptor

EDIT: this particular bug relating to ‘verbless grammar’ (the Darcy, … snippet problem) appears to have been fixed in Ver 10.1, although the other problems identified in this thread persist.

2 Likes

This is one potential fix for the ‘Darcy, …’ error

Include (- Global save_verb_wordnum; -) after "Definitions.i6t". [to store verb_wordnum before it is set to 0 by UnknownVerb()]
Include (- Replace UnknownVerb OriginalUnknownVerb; -) after "Definitions.i6t". [run our new routine first, which will then call the original]
Include (- [UnknownVerb ;  save_verb_wordnum = verb_wordnum; return OriginalUnknownVerb(); ]; -) after "Output.i6t". [make sure it comes after the original UnknownVerb in the output I6. (- Replace MyFunction OldMyFunction; -) must precede any declaration of MyFunction() but may be followed by any number of subsequent declarations of MyFunction(). The MyFunction chosen to compile will be the last-defined version, except that definitions in normal files are always preferred over definitions in System_file files or the veneer. With the two-parameter form (introduced in 6.33), the declaration chosen to be renamed and compiled as OldMyFunction will be the first-declared version of the function.]

the following replacement code for section ‘D’ of the parser can be included as an alternative to replacing UnknownVerb if working with a version of Inform6 preceding an easily- predictable two-parameter Replace statement (i.e. prior to 6.34). Either way, the replacement below for section ‘H’ of the parser must be included.

[Include (-
	.NotConversation;
	! ### Insertion
	save_verb_wordnum = verb_wordnum;  !#### in case it is set to 0 by UnknownVerb but needed later by default ##Answer 
	! ### Insertion ends
	if (verb_word == 0 || ((verb_word->#dict_par1) & 1) == 0) {
		! print "Calling UnknownVerb...^";
		verb_word = UnknownVerb(verb_word);
		if (verb_word ~= 0) jump VerbAccepted;
		best_etype = VERB_PE;
		jump GiveError;
	}
	.VerbAccepted;

	! We now definitely have a verb, not a direction, whether we got here by the
	! "take ..." or "person, take ..." method.  Get the meta flag for this verb:

	meta = ((verb_word->#dict_par1) & 2)/2;

	! You can't order other people to "full score" for you, and so on...

	if (meta == 1 && actor ~= player) {
		best_etype = VERB_PE;
		meta = 0;
		jump GiveError;
	}

	! Now let i be the corresponding verb number...

	i = DictionaryWordToVerbNum(verb_word);

	! ...then look up the i-th entry in the verb table, whose address is at word
	! 7 in the Z-machine (in the header), so as to get the address of the syntax
	! table for the given verb...

	#Ifdef TARGET_ZCODE;
	syntax = (HDR_STATICMEMORY-->0)-->i;
	#Ifnot; ! TARGET_GLULX
	syntax = (#grammar_table)-->(i+1);
	#Endif; ! TARGET_

	! ...and then see how many lines (ie, different patterns corresponding to the
	! same verb) are stored in the parse table...

	num_lines = (syntax->0) - 1;

	! ...and now go through them all, one by one.
	! To prevent pronoun_word 0 being misunderstood,

	pronoun_word = NULL; pronoun_obj = NULL;

	#Ifdef DEBUG;
	if (parser_trace >= 1)
		print "[Parsing for the verb '", (address) verb_word, "' (", num_lines+1, " lines)]^";
	#Endif; ! DEBUG

	best_etype = STUCK_PE; nextbest_etype = STUCK_PE;
	multiflag = false;

	! "best_etype" is the current failure-to-match error - it is by default
	! the least informative one, "don't understand that sentence".
	! "nextbest_etype" remembers the best alternative to having to ask a
	! scope token for an error message (i.e., the best not counting ASKSCOPE_PE).
	! multiflag is used here to prevent inappropriate MULTI_PE errors
	! in addition to its unrelated duties passing information to action routines

-)  instead of "Parser Letter D" in "Parser.i6t".]
Include (-
  .GiveError;

	etype = best_etype;
	if (actor ~= player) {
		if (usual_grammar_after ~= 0) {
			verb_wordnum = usual_grammar_after;
			jump AlmostReParse;
		}
		! ### Insertion ##############################################################
		!print "Saved verb word number: ", save_verb_wordnum, " Verb word number: ", verb_wordnum, "^";
		if ((save_verb_wordnum ~= 0) && (verb_wordnum == 0)) verb_wordnum = save_verb_wordnum;
		! ### Insertion ends ##########################################################
		wn = verb_wordnum;
		special_word = NextWord();
		if (special_word == comma_word) {
			special_word = NextWord();
			verb_wordnum++;
		}
		parser_results-->ACTION_PRES = ##Answer;
		parser_results-->NO_INPS_PRES = 2;
		parser_results-->INP1_PRES = actor;
		parser_results-->INP2_PRES = 1; special_number1 = special_word;
		actor = player;
		consult_from = verb_wordnum; consult_words = num_words-consult_from+1;
		rtrue;
	}
-) instead of "Parser Letter H" in "Parser.i6t".
1 Like

Having perused the parser again in more detail, this simple tweak may well deal with both issues: the failure to consider ‘no.verb’ grammar lines having failed to match any grammar lines with a recognised verb, and the bug associated with ‘Answering someone that’ via ‘someone, …’ style commands when grammar lines exist that begin with a token and generate ‘no.verb’.

Not exhaustively tested, but in principle…

"___Fix_Verbless_Actions" by PB

Chapter - Setup

Section - Setting up so UnknownVerb() returns 'no.verb' and 'employ' is ambiguous as a verb or 'no.verb'

To handle is a verb. To strut is a verb.
Understand "employ subterfuge/deceit/deception/wiles" as deceiving.
Understand "employ/deploy/utilise/use" as "[utilising]".
Understand "[utilising] [something]" as using.
Using is an action applying to one thing.
Deceiving is an action applying to nothing.
Report an actor deceiving: say "[The actor] [strut] around the room, maintaining a pretence of indifference to [their] surroundings.".
Report an actor using: say "[The actor] [handle] [the noun] with the accomplishment born of faultless breeding.".

Chapter - Fix

Section - Fix for incorrect snippet generation when UnknownVerb() returns 'no.verb' and command of form 'Darcy, splendid coat' is diverted to ##Answer, by correct reset of verb_wordnum

Include (- Replace UnknownVerb; -) after "Definitions.i6t". [run our new routine instead]
Include (- [UnknownVerb; verb_wordnum--; return 'no.verb'; ]; -) [move verb_wordnum back to 0 if still searching for verb as first word of command, or back to the comma if a command like 'Darcy, ....'] after "Output.i6t". [make sure it comes after the original UnknownVerb in the output I6. (- Replace MyFunction [OldMyFunction]; -) must precede any declaration of MyFunction() but may be followed by any number of subsequent declarations of MyFunction(). The MyFunction chosen to compile will be the last-defined version, except that definitions in normal files are always preferred over definitions in System_file files or the veneer. With the two-parameter form (introduced in 6.33), the declaration chosen to be renamed and compiled as OldMyFunction will be the first-declared version of the function.]

Section - Fix for failure to consider 'no.verb' grammar lines when no grammar lines match for a detected verb

[if we've reached this point all grammar lines for the recognised verb have failed, so if we haven't tried 'no.verb' and UnknownVerb() returns 'no.verb'- indicating at least some 'no.verb' grammar lines, try those]

Include (- if ((verb_word ~= 'no.verb') && (verb_word =UnknownVerb(verb_word))) jump VerbAccepted; -) after "Parser Letter G" in "Parser.i6t".

Chapter - Scenario

Netherfield Hall is a room. "A soaring space of oak-panelled grandeur, with a small doorway to the north.".
The workbench is here. The sideboard is here. The walnut box is a closed opaque openable container. it is on the workbench. The teatray is a portable supporter. It is on the sideboard. The teapot is on the teatray. The hat is a wearable thing. It is on the workbench. A Walnut Whip is an edible thing in the box. The knife, the fork, the apple, the salad server and the cruets are on the sideboard. Cutlery is a kind of thing. The knife and fork are cutlery. The apple is edible. The cruets are plural-named. The thingumajig is nowhere. In Netherfield Hall is a man called Mr Darcy. Darcy is proper-named. Mr Darcy wears a blue frock coat. The initial appearance of Mr Darcy is "Mr Darcy haughtily haunts the hall." In Netherfield Hall is a woman called Miss Elizabeth Bennett. The printed name of Elizabeth is "Miss Bennett". Elizabeth is proper-named. Elizabeth wears a shawl.  The initial appearance of Elizabeth is "Miss Bennett sits demurely, while her glance flits penetratingly over her surroundings." The cupboard is an open, opaque, openable, enterable, fixed in place container. It is in Netherfield Hall.
There is an open door called the parlour door.  The indefinite article of parlour door is "the". There is a room called The Parlour. It is north of the parlour door.  The parlour door is north of Netherfield Hall. The plucked pheasant is in the Parlour.  The oak shelving is a backdrop. It is not scenery. The shelving is in the Parlour and Netherfield Hall. The indefinite article of the shelving is "some". Netherfield Park is a region. Netherfield Hall and the Parlour are in Netherfield Park.

The player carries an animal called the hamster. The player wears a pair of glasses. The glasses are plural-named. The indefinite article of the glasses is "a". The player carries a closed openable transparent container called the glass jam jar. The starfish is an animal. It is in the glass jam jar.


Chapter - Testing

Section - Machinery
	
Persuasion: rule succeeds.

Instead of answering Miss Bennett that when the topic understood includes "netherfield": say "Charming, [if Mr Darcy is in the location]is it not, Darcy[else] don't you agree[end if]?".
To regard is a verb.
Instead of answering Darcy that when the topic understood includes "collins": say "[Mr Darcy] [regard] [us] silently, with an exquisitely pained expression.".

Section - Test Scripts

Test me with "actions / Darcy, I believe Mr Collins has had the remarkable good fortune to shoot a peacock / employ deceit / Miss Bennett, what is your opinion of Netherfield? / Darcy, employ subterfuge / Elizabeth, employ the salad server".
1 Like

Interesting. I didn’t even realize that the grammar was theoretically forbidden.

I will study your suggestions. Thank you!

What Inform really wants you to do is to separate out these alternatives like so:

Understand "employ [something]" or "deploy [something]" or "utilise [something]" or "use [something]"  as using.

so that it can create a grammar line and put a verb word into the dictionary for each case, rather than relying on calling a prepositional GPR routine to deal with all ‘pseudo-verb’ cases under cover of a hacky ‘no.verb’ grammar line, i.e.:

Verb 'employ'
    * noun  -> A78_using
;
Verb 'deploy'
    * noun  -> A78_using
;
Verb 'utilise'
    * noun  -> A78_using
;
Verb 'use'
    * noun  -> A78_using
;

rather than

Verb 'no.verb'
    * GPR_Line_94 noun  -> A78_using
;

I guess the comment ‘at the moment…’ in the compiler error brought up by trying to do things the ‘wrong way’ is a recognition that the compiler could in principle choose to do the job of separating out alternate verb words given at the start of an I7 ‘Understand grammar’ declaration, giving each their own I6 grammar line instead of substituting a single GPR routine, but at present doesn’t do so…

The presence of the obvious ‘Someone, …’ bug in the presence of any ‘no.verb’ grammar lines and the ‘not taking account of ambiguous verb/no.verb definitions’ bug you uncovered suggests that the whole concept of ‘verbless grammar’ in Inform remains a little ramshackle in implementation and has never been subject to much testing.

Despite the above potential ‘fixes’, I suspect ‘verbless grammar’ is best avoided unless there really is no alternative. Of course, in desperation it would be possible to extend the UnknownVerb() entry point to return a ‘proper’ verb instead of ‘no.verb’, or use the LanguageIsVerb() entry point (designed I think for languages where the verb doesn’t come first in imperative sentences, or may comprise more than one word), although I’m not immediately sure what cases in English would make either worth the trouble.

@drpeterbatesuk, this was very neatly done, and it’s a surgical proof of concept. I am curious whether @zarf (or others) can point out any potential downsides. (None are obvious to me, but I’ve yet to fully comprehend the core parser code.)

Again, thank you.

P.S. Just in case you haven’t run across it, you can use “before” just like “after” when placing Include contents, and you can name the subsection of a template file, too, so I modified your code slightly to

Include (- Replace UnknownVerb; -) before "Grammar" in "Output.i6t". [run our new routine instead]
Include (- [ UnknownVerb; verb_wordnum--; return 'no.verb'; ]; -) after "Grammar" in "Output.i6t". [move verb_wordnum back to 0 if still searching for verb as first word of command, or back to the comma if a command like 'Darcy, ....']

which still passes the provided test cases.

1 Like

One issue that remains unresolved by the above fixes is that the parser has no simple way of recognising that a new command in the form of a ‘no.verb’ grammar line has been typed at a disambiguation prompt in lieu of an answer to the disambiguation question. The present parser code relies on finding one of: a (genuine) verb as the first word; or a verb being returned by LanguageIsVerb() (if defined); or the presence of a comma somewhere in what is typed to suggest a new attempt at conversation in the form ‘Someone, …’ (which is why test case [11] works ok); in order to divert entry at the disambiguation prompt to parsing a new command rather than disambiguating the last.

Consequently, typing ‘use fork’ at a disambiguation prompt leads to ‘use fork’ being inserted into the previous command as an answer to the disambiguation question and an attempt at reparsing something like ‘take use fork walnut’, usually with ‘I didn’t understand that sentence’ as a result. I can’t see a simple solution to this: although irritating it’s unlikely to cause much of an issue in practice.

Another edge case for which a fix is provided below arises when issuing a chain of commands to an NPC. verb_wordnum now ‘sits upon’ the comma after processing ‘no.verb’ commands such as the first in ‘Darcy, use knife. take fork’. The code that erases the processed first command from the input buffer before moving on to parse the second starts from verb_wordnum, so erases the comma too, leading to an attempt to parse ‘darcy take fork’ and therefrom to ‘I did not understand that sentence.’

The fix below nudges verb_wordnum forward by one, past the comma, to deal with this case.
NB the location of the erasure code was moved at some point from Parser Letter K to Parser Letter A so this fix (at least insofar as it is included before Parser Letter A) is only guaranteed to work for Inform 6M62

As a bonus, I’ve included a fix for another issue I came across in testing, whereby an attempt to test for an included text in a zero-length snippet throws a programming error, unless the snippet is of numeric value 100, which is special-cased. I’m not sure why 200, 300 etc. aren’t included in this special-casing, but the issue came to light because ‘darcy,’ generates a topic understood of “” represented by a snippet of numeric value 300.

"___Fix_Verbless_Actions Ver2" by PB

Chapter - Setup

Section - Setting up so UnknownVerb() returns 'no.verb' and 'employ' is ambiguous as a verb or 'no.verb'

To handle is a verb. To strut is a verb.
Understand "employ subterfuge/deceit/deception/wiles" as deceiving.
Understand "employ/deploy/utilise/use" as "[utilising]".
Understand "[utilising] [something]" as using.
Using is an action applying to one thing.
Deceiving is an action applying to nothing.
Report an actor deceiving: say "[The actor] [strut] around the room, maintaining a pretence of indifference to [their] surroundings.".
Report an actor using: say "[The actor] [handle] [the noun] with the accomplishment born of faultless breeding.".

Chapter - Fix (Inform 6_34)

Section - Fix for incorrect snippet generation when UnknownVerb() returns 'no.verb' and command of form 'Darcy, splendid coat' is diverted to ##Answer, by correct reset of verb_wordnum

Include (- Replace UnknownVerb; -) after "Definitions.i6t". [run our new routine instead]
Include (- [UnknownVerb; verb_wordnum--; return 'no.verb'; ]; -) [move verb_wordnum back to 0 if still searching for verb as first word of command, or back to the comma if a command like 'Darcy, ....'] after "Output.i6t". [make sure it comes after the original UnknownVerb in the output I6. (- Replace MyFunction [OldMyFunction]; -) must precede any declaration of MyFunction() but may be followed by any number of subsequent declarations of MyFunction(). The MyFunction chosen to compile will be the last-defined version, except that definitions in normal files are always preferred over definitions in System_file files or the veneer. With the two-parameter form (introduced in 6.33), the declaration chosen to be renamed and compiled as OldMyFunction will be the first-declared version of the function.]

Section - Fix for comma being erased from chained commands to NPC following a 'no.verb' command (eg test case [11]) by nudging verb_wordnum forward by 1, past the comma

Include (-
if ((held_back_mode) && (verb_wordnum ~=0)){
	wn = verb_wordnum;
	if (NextWordStopped() == comma_word) verb_wordnum++;
};
-) before "Parser Letter A" in "Parser.i6t".	  

Section - Fix for failure to consider 'no.verb' grammar lines when no grammar lines match for a detected verb

[if we've reached this point all grammar lines for the recognised verb have failed, so if we haven't tried 'no.verb' and UnknownVerb() returns 'no.verb'- indicating at least some 'no.verb' grammar lines, try those]

Include (- if ((verb_word ~= 'no.verb') && (verb_word =UnknownVerb(verb_word))) jump VerbAccepted; -) after "Parser Letter G" in "Parser.i6t".

Section - Bonus Fix  Inappropriate RTP error generated by 'when the topic understood includes __' when the topic understood is "" eg after 'Darcy,' which generates ##Answer action with parsed_number 300

Include (- Replace SnippetIncludes; -) after "Definitions.i6t".

Include (- 

[ SnippetIncludes test snippet w1 w2 wlen i j;
	w1 = snippet/100; w2 = w1 + (snippet%100) - 1;
	if ((w2<w1) || (w1<1)) {
		if ((w1 == 1) && (w2 == 0)) rfalse; ! #### pre-existing special-case for snippet of 100
		! ##### Insertion
		!print "w1=",w1," w2=",w2,"^";
		if ((snippet%100) == 0) rfalse;  ! 100, 200, 300 etc. i.e. snippet is ""
		! ##### Insertion ends
		return RunTimeProblem(RTP_INCLUDEINVALIDSNIPPET, w1, w2);
	}
	if (metaclass(test) == Routine) {
		wlen = snippet%100;
		for (i=w1, j=wlen: j>0: i++, j-- ) {
			if (((test)(i, 0)) ~= GPR_FAIL) return i*100+wn-i;
		}
	}
	rfalse;
];
-) after "Output.i6t".


Chapter - Scenario

Netherfield Hall is a room. "A soaring space of oak-panelled grandeur, with a small doorway to the north.".
The workbench is here. The sideboard is here. The walnut box is a closed opaque openable container. it is on the workbench. The teatray is a portable supporter. It is on the sideboard. The teapot is on the teatray. The hat is a wearable thing. It is on the workbench. A Walnut Whip is an edible thing in the box. The knife, the fork, the apple, the salad server and the cruets are on the sideboard. Cutlery is a kind of thing. The knife and fork are cutlery. The apple is edible. The cruets are plural-named. The thingumajig is nowhere. In Netherfield Hall is a man called Mr Darcy. Darcy is proper-named. Mr Darcy wears a blue frock coat. The initial appearance of Mr Darcy is "Mr Darcy haughtily haunts the hall." In Netherfield Hall is a woman called Miss Elizabeth Bennett. The printed name of Elizabeth is "Miss Bennett". Elizabeth is proper-named. Elizabeth wears a shawl.  The initial appearance of Elizabeth is "Miss Bennett sits demurely, while her glance flits penetratingly over her surroundings." The cupboard is an open, opaque, openable, enterable, fixed in place container. It is in Netherfield Hall.
There is an open door called the parlour door.  The indefinite article of parlour door is "the". There is a room called The Parlour. It is north of the parlour door.  The parlour door is north of Netherfield Hall. The plucked pheasant is in the Parlour.  The oak shelving is a backdrop. It is not scenery. The shelving is in the Parlour and Netherfield Hall. The indefinite article of the shelving is "some". Netherfield Park is a region. Netherfield Hall and the Parlour are in Netherfield Park.

The player carries an animal called the hamster. The player wears a pair of glasses. The glasses are plural-named. The indefinite article of the glasses is "a". The player carries a closed openable transparent container called the glass jam jar. The starfish is an animal. It is in the glass jam jar.


Chapter - Testing

Section - Machinery
	
Persuasion: rule succeeds.

Instead of answering Miss Bennett that when the topic understood includes "netherfield": say "Charming, [if Mr Darcy is in the location]is it not, Darcy[else] don't you agree[end if]?".
To regard is a verb.
Instead of answering Darcy that when the topic understood includes "collins": say "[Mr Darcy] [regard] [us] silently, with an exquisitely pained expression.".

Section - Test Scripts

Test me with "Darcy, I believe Mr Collins has had the remarkable good fortune to shoot a peacock / use fork / employ deceit / Miss Bennett, what is your opinion of Netherfield? / Darcy, employ subterfuge / Elizabeth, employ the salad server / darcy, open box / take walnut / use fork / darcy, take walnut / darcy, use fork. use knife / elizabeth, take walnut / elizabeth, employ wiles / darcy,".

[unfixed problems:
	(i) 'no.verb' typed at a disambiguation prompt e.g. 'use fork' in test case [9] leads to a command with 'use fork' inserted at the disambiguation point being passed to the parser, e.g. 'take use fork walnut']
	

Ha! 'Tis a capricious and ancient beast laired in a weed-infested back yard of code, patchily annotated, strewn left and right with special-cases, deprecated byways, and flimsy superstructures, all built upon shifting sands. Any tinkering with it is fraught with peril and the likelihood of unleashing a cascade of unintended consequences upon any number of unimagined edge cases. He who would valiant be… A little intellectual jousting aside, wise men counsel doing nothing to provoke it. :wink:

2 Likes