Does the player mean

Hello,

I’ve been having some trouble with “Does the player mean”. I have a number of tickets and I am trying to disambiguate them. In two cases it’s working as expected, but the last case doesn’t seem to happen.

Can anyone explain what is going on here?

the FW-room is a room. the printed name is "Ferris Wheel".
the Ferris Wheel Attendant is a man in the FW-room. The description is "This is a bored teenager.".
a thing called the Ferris Wheel is here. it is a backdrop. the Ferris Wheel is everywhere. The description of the Ferris Wheel is "This is the Ferris wheel.". 

a thing called the Fortune Teller ticket is carried by the player. The description of the fortune teller ticket is "'Admit One' Have your fortune told.".
a thing called Ferris Wheel ticket is carried by the player. The description of the ferris wheel ticket is "'Admit One' to the Ferris Wheel.".
a thing called the Carousel ticket is carried by the player. The description of the carousel ticket is "'Admit One' to the Carousel.".
The player carries a parking ticket. The description is "This is your receipt for parking.".

Does the player mean examining the Ferris Wheel when the location is the FW-room: it is very likely.
Does the player mean examining the Ferris Wheel ticket when the location is the FW-room: it is likely.
Does the player mean giving the Ferris Wheel ticket to the ferris wheel attendant: it is very likely.

test me with "x ferris wheel / x ticket / give ticket / give ticket to attendant".

I do not have a perfect solution, but I noticed that:

Does the player mean doing something with the Ferris Wheel ticket when (the location of the player is the FW-room) and (the Ferris Wheel attendant is in the location of the player): it is very likely.

seems to produce a better result.

>give ticket
(Ferris Wheel ticket to the Ferris Wheel Attendant)
The Ferris Wheel Attendant doesn't seem interested.

>give ticket to attendant
(Ferris Wheel ticket to the Ferris Wheel Attendant)
The Ferris Wheel Attendant doesn't seem interested.
2 Likes

There’s something in the docs about commands with two nouns, perhaps relevant:

https://zedlopez.github.io/i7doc/WI_17.html#section_19

Docs Snippet

But there is a caveat. There are some cases where this mechanism will not in fact help Inform to choose its way out of an ambiguous command, because of the way it parses one noun at a time. It usually needs to understand the first noun before it will even try to make sense of the second. So a rule like:

Does the player mean throwing the can of shoe polish at the tree: it is likely.

may not work if the player types THROW POLISH AT TREE and POLISH is ambiguous, because when the parser is trying to understand POLISH, it hasn’t yet seen to the end of the command and realised that the second noun will be the tree; so the second noun is unset and the rule won’t match.

If you do a trace (type TRACE 4 at the prompt), it appears that the tickets all have matching scores. Since they shouldn’t all match, I assume the DTPM rule is dropped.

If you name the ticket fully in the test commands, everything appears to go through. Which isn’t a huge help, I know. I think @Monsieur.HUT has a good answer. Since nobody else will take it, specifying the location should be sufficient.

Someone clever may have more to say about the DTPM process, I just bang my way through things…

3 Likes

There are two separate issues:

  1. It looks like some parser state is not being reset in the particular path of the testing commands: specifically, the way that it tries to parse a command after an aborted “which do you mean?” question is not quite the same as it is after a command has been successfully interpreted. You can see the difference if you do >GIVE TICKET TO ATTENDANT before >GIVE TICKET. (In this case, I think that the problem comes from cobj_flag not being reset at point .ReParse, or alternatively within NounDomain()'s .RECONSTRUCT_INPUT block before returning REPARSE_CODE. The issue can be fixed if you want to do a little mad science.)

  2. The way that you’ve phrased your DTPM rules is contributing somewhat, though I would say they are written correctly. If you change giving the Ferris Wheel ticket to the attendant to just giving the Ferris Wheel ticket to, you will see better results in your original scenario. The reason is that for the command >GIVE TICKET, the second noun will be set to nothing, which does not match the rule’s preamble. By leaving out a second noun, the rule’s applicability is broadened – but the downside is that it will want to give the ticket to any second person, which I doubt would work well for your scenario.

The reason that the version of the DTPM rule that you wrote is not working as expected is that the parser code involved does not allow “inference” of the second noun in this situation. I don’t see any good reason that inference would be deliberately prevented, so perhaps it’s just an oversight or minor bug. It’s a small change to modify the ChooseObjects() routine to allow inference of the second noun, and then the original DTPM rule that you wrote will work correctly with the incomplete command >GIVE TICKET.

Here’s a 10.1.2 compatible change:

Include (-

	[ ChooseObjects obj code  l i swn spcount;
		if (code<2) rfalse;

		if (cobj_flag == 1) {
			.CodeOne;
			if (parameters > 0) {
				#ifdef COBJ_DEBUG;
				print "[scoring ", (the) obj, " (second)]^";
				#endif;
				return ScoreDabCombo(parser_results-->INP1_PRES, obj);
			} else {
				#ifdef COBJ_DEBUG;
				print "[scoring ", (the) obj, " (first) in ",
					alt_match_list-->0, " combinations]^";
				#endif;
				l = 0;
				for (i=1: i<=alt_match_list-->0: i++) {
					spcount = ScoreDabCombo(obj, alt_match_list-->i);
					if (spcount == HIGHEST_DPMR_SCORE) {
						#ifdef COBJ_DEBUG;
						print "[scored ", spcount, " - best possible]^";
						#endif;
						return spcount;
					}
					if (spcount>l) l = spcount;
				}
				return l;
			}
		}
		if (cobj_flag == 2) {
			.CodeTwo;
			#ifdef COBJ_DEBUG;
			print "[scoring ", (the) obj, " (simple); parameters = ", parameters,
				" aw = ", advance_warning, "]^";
			#endif;
			@push action_to_be;
			if (parameters==0) {
				if (advance_warning > 0)
					l = ScoreDabCombo(obj, advance_warning);
				else
					l = ScoreDabCombo(obj, 0);
			} else {
				l = ScoreDabCombo(parser_results-->INP1_PRES, obj);
			}
			@pull action_to_be;
			return l;
		}

		#ifdef COBJ_DEBUG;
		print "[choosing a cobj strategy: ";
		#endif;
		swn = wn;
		spcount = pcount;
		while (line_ttype-->pcount == PREPOSITION_TT) pcount++;
		if (line_ttype-->pcount == ELEMENTARY_TT) {
			if (line_tdata-->pcount == TOPIC_TOKEN) {
				pcount = spcount;
				jump CodeTwo;
			}
			while (wn <= num_words + 1) {	! MODIFIED
				l = NextWordStopped(); wn--;
				if (l == THEN1__WD) break;
				if ( (l ~= -1 or 0) && (l->#dict_par1) &8 ) { wn++; continue; }	! if preposition
				if (l == ALL1__WD or ALL2__WD or ALL3__WD or ALL4__WD or ALL5__WD) { wn++; continue; }
				SafeSkipDescriptors();
				! save the current match state
				@push match_length; @push token_filter; @push match_from;
				alt_match_list-->0 = number_matched;
				COBJ__Copy(number_matched, match_list, alt_match_list+WORDSIZE);
				! now get all the matches for the second noun
				match_length = 0; number_matched = 0; match_from = wn;
				token_filter = 0;
				SearchScope(actor, actors_location, line_tdata-->pcount);
				#ifdef COBJ_DEBUG;
				print number_matched, " possible second nouns]^";
				#endif;
				wn = swn;
				cobj_flag = 1;
				! restore match variables
				COBJ__SwapMatches();
				@pull match_from; @pull token_filter; @pull match_length;
				pcount = spcount;
				jump CodeOne;
			}
		}
		pcount = spcount;
		wn = swn;	
		
		#ifdef COBJ_DEBUG;
		print "nothing interesting]^";
		#endif;
		cobj_flag = 2;
		jump CodeTwo;
	];

-) replacing "ChooseObjects".
3 Likes

Are you still looking for a solution to this problem?

actually, i am still struggling with this but i can’t isolate the behavior in a sample source. i created one using as much of my original source as i could but could not repro.

the issue is that i have two items that are backdrops and two tickets

a thing called hell ride is a backdrop.
a thing called hell ride ticket is carried by the player.
a thing called ferris wheel is a backdrop.
a thing called a ferris wheel ticket is carried by the player.

does the player mean doing something with hell ride: it is very likely.
does the player mean doing something with the hell ride ticket: it is likely.

does the player mean doing something with ferris wheel: it is very likely.
does the player mean doing something with the ferris wheel ticket: it is likely.

there are other conditions them making them more specific but the code is identical.

>x ferris wheel
you see the ferris wheel.

> x ticket
(ferris wheel ticket)
it's the ferris wheel ticket

>x hell ride
You can't use multiple objects with that verb.

d.

I would guess that this is a situation where the I7 compiler is assuming that a reference to hell ride is, in fact, the hell ride ticket.

If I’m recalling correctly, it has a tendency to match against the most recent reference. In this case, you mention the hell ride ticket then have a DTPM rule regarding the hell ride.

You can either Use unabbreviated object names. to force a full match, or you can use different Section/Chapter/etc. headings and place the rides and the tickets in separate sections. (The I7 compiler prioritizes matches within the same section in cases of ambiguity.)

[EDIT: I’m not sure what I was thinking when I typed this. The advice might be useful in some other context, but it can’t have been the cause of the output you show. (Even if the compiler was assuming a DTPM rule applied to the wrong object, that would still give different weights to the two objects.) Sorry about that!]

2 Likes

Thank you for your thoughts. i didn’t realize that different chapters/sections would make a difference.

d.

i JUST found this thread. DTPM disambiguations don't run on scenery [Does The Player Mean]

I have to go grok it. But it seems to say there is wonkiness with the DTPM rules and scenery (backdrops like i have).

I think I misunderstood the nature of your current problem. Based on the I6 output in 6M62, the I7 compiler is probably not getting confused about the two objects (hell ride vs. hell ride ticket).

Are you talking about this response?

>x hell ride
You can't use multiple objects with that verb.

… and the problem is that you were expecting the parser to automatically pick the hell ride because of your following DTPM rule?

does the player mean doing something with hell ride: it is very likely.

Once you learn to decipher it, you can get a lot of insight into what the parser is doing with the >TRACE debugging verb.

What is the output when you try >TRACE 5 then >X HELL RIDE?

Hello,

Thanks for your continued assistance with this. that is exactly the outcome and expectation. Trace 5 generates a lot of output.

X_Hell_Ride_Trace_5.txt (8.5 KB)

OK. In the future, you can put that kind of thing inside a “hide details” block instead of uploading a file – less hassle all around.

The output shows that something is causing the parser to think the words “hell ride” should be interpreted as meaning a plural encompassing both the ride itself and the ticket for the ride. This is not normal, so something in your code is probably causing that (unless it’s an extension). This would typically be an Understand ... as the plural of ... directive.

If you have any statements along the lines of:

Understand "hell ride" as the plural of hell ride ticket.
Understand "hell ride" as the plural of hell ride.

then try removing them – they wouldn’t be doing anything useful.

The only use of plural was in this code:

A ride ticket is a kind of thing. A ride ticket has a price. The plural of ride ticket is ride tickets.
a thing called a Hell Ride ticket is a ride ticket. the cashier carries the hell ride ticket. the price is $4.00. the description is "Admit One - Hell Ride".

removing the plural reference didn’t change things

OK. That’s definitely the culprit, and I think it qualifies as a bug in the I7 compiler.

Here’s the some reproduction code showing the bug in 6M62 and 10.1.2:

Place is a room.

There is a backdrop called the hell ride. It is everywhere.
There is a backdrop called the ferris wheel. It is everywhere.

does the player mean doing something with hell ride: it is very likely.
does the player mean doing something with the hell ride ticket: it is likely.

does the player mean doing something with ferris wheel: it is very likely.
does the player mean doing something with the ferris wheel ticket: it is likely.

A ride ticket is a kind of thing. [<-- problem line]
The player carries a ride ticket called a Hell Ride ticket.
The player carries a ride ticket called a Ferris Wheel ticket.

Test me with "x hell ride".

The I7 compiler is marking all words in the multi-word kind name for ride ticket as plural, which would not generally be desirable. You can see the effect in generated I6 for the ticket objects:

Object -> I139_hell_ride_ticket ""
	class K16_ride_ticket
	with name 'hell' 'ride' 'ticket'  'tickets//p'	! 'ride//p' suppressed due to 'ride' being part of object name?
	...
;

Object -> I140_ferris_wheel_ticket ""
	class K16_ride_ticket
	with name 'ferris' 'wheel' 'ticket' 'ride//p' 'tickets//p'	! 'ride//p' unexpectedly marked plural
	...
;

This happens whether or not you provide an explicit plural, because the compiler will construct a default plural if none is specified. If I’m remembering correctly, this is something noted by @drpeterbatesuk a while back, so it may already have been reported. In the meantime, I’m pinging @Zed and @Draconis to take a look at this in case they have other thoughts.

My short term suggestion would be to rename the kind to attraction ticket or similar.

1 Like

thank you! i understand the confusion now.

Yes, Inform’s default plural name handling leaves a lot to be desired, and this is only the latest in a long line of bugs coming from it.

When it constructs an automatic plural name, only the final word in that name should get the /p flag in the dictionary.

1 Like