Yeah, having run into similar issues, one philosophical thing it helped to get my head around is that I think the Inform parser considers the disambiguation prompt kind of a failure – like, it really wants to understand what you typed first time round and not have to bug you with a follow-up question, so it’ll default to something unless it’s really a close-run thing. So I think authors are intended to approach implementation in much the same way, suppling Does the Player Mean rules and other Understand grammar to resolve ambiguity as much as possible. Of course there are situations where that’s easier said than done, but it can be annoyingly hard to intentionally get the parser to ask the follow-up question, because it feels like it really really wants to guess rather than ask and make sure.
More practically in terms of getting to the bottom of these problems, Daniel’s mentioned the TRACE command, which comes in flavors of increasing complexity – I find it’s very useful for enabling me to squint at the screen and feel befuddled, but you can at least usually see which candidate words are being accepted and rejected and with what weights. RULES would also let you catch the initial thing you ran into (the broad Does the Player Mean statement).
Anyway beyond the I6 hack Daniel’s pulled together, I think for cases like this as a matter of design I’d try to push the parser to default to examining the piece of paper in the location, not the one that’s being carried, because presumably the player’s already looked at the one they’re carrying. And so long as they’ve got sufficiently distinct names, the little parenthetical telling the player what the parser’s done should make it simple enough to type a more specific follow-up command if they actually wanted to look at the other one.
(Also, yes, identical items are a giant bear. The climactic puzzle of my first game involved hiding ten identical bits of statuary in different places around an apartment, and I will never attempt anything like that ever again – there’s still a bug I haven’t been able to fully reproduce where trying to take one of the bits out of the fireplace and lead you to taking one hidden in a friend’s tunic instead. It’s maddening!)
My biggest mystery was a room that had both “worthless stuff” and “nerd stuff.” A “FROB STUFF” command always assumed that the player meant the “worthless stuff” which is, as promised, pretty worthless. Neither thing can be carried (scenery). My only guess was that the “worthless stuff” was mentioned first, but that doesn’t sound right. I’ll try to trace it if I don’t have to muck up my code to do it.
It was easily chased off because “worthless stuff” is an internal name that the player never needs to input, but I’m curious about it anyway.
Now that I think about it: the worthless stuff is in a container, while the nerd stuff is on a supporter. That’s room’s a real party.
e: ten points! wonder if that’s container vs supporter, can’t tell
Scoring match list: indef mode 0 type 0, satisfying 0 requirements:
the tumblers and forks in the sink (979883) in the kitchen sink : 2136 points
The nerd stuff (979947) in the kitchen countertop : 2126 points
Single best-scoring object returned.]
[ND returned the tumblers and forks in the sink]
Fortunately, the different factors that go into the scoring vary enough that we can make a good guess as to what’s going on!
The factors are:
1000 points for ChooseObjects preferring it (a separate library routine that does some magic of its own)
500 points for being “good”, which is never actually used anywhere
100 points for not having the I6 concealed flag, which is only ever used for the player character
60 points for being in the best location (usually held)
40 points for being in the next-best location (usually the player’s location)
20 points for not being a direction
10 points for not being scenery
5 points for not being the actor
1 point for matching the gender, number, and animacy restrictions of a word in the input (this matters for e.g. German where the gender of the article should be taken into account)
So to get 2136 vs 2126 points, I’m guessing that’s:
2000 points from ChooseObjects
100 points for not being the player
20 points for not being a direction
5 points for not being the actor
1 point for matching the gender, number, and animacy
Which means there’s a 10-point contribution from somewhere. The only way to get exactly 10 points on top of all that would be if the parser thinks the nerd stuff is scenery, and the worthless stuff is not.
…honestly, as I look at all of this, I’m starting to wonder if this wouldn’t be a good use of an activity. Replace ScoreMatchL with an activity or rulebook that the author can customize each step of.
“Should the parser prefer scenery: decrease the consideration score by 10.”
Someone may well have already done this, I have a dim memory of a “should the parser prefer” rulebook, but I can’t seem to find it now.
EDIT: Ah, with a bit more searching I see that the ChooseObjects routine basically just delegates to the “does the player mean” rulebook. Okay, so the intent is that DTPM rules override all of this (with a score of 1000) and this is the fallback if those fail.
I still wonder if this should be more exposed to the I7 side.
Oh man, I hear you. Did a game where almost every room had a light switch, and one had two and that was a never-ending nightmare.
I think the intended ideal is you should in general avoid identical-but-importantly-different bits of anything. Identical things are covered by kinds (leaves, jellybeans, coins), similar things need different adjectives (frayed scroll, tattered scroll, charred scroll), and that’s where disambiguation is supposed to take up the slack. Anyone who’s had a game with multiple letters or notes has run into this.
Holy cow, is this stubborn behavior. I have four DTPM rules now trying to turn off doing things to the carried paper when in the location of the not-carried paper, and it STILL wants to pick the carried paper:
Does the player mean doing something to something carried:
it is unlikely.
Does the player mean doing something to the carried paper:
if the location is stream:
it is very unlikely.
Does the player mean doing something to the not-carried paper:
it is very likely.
Does the player mean taking something carried:
it is very unlikely.
All this and I still get this:
> **get paper**
(torn piece of paper with some writing on it)
You already have it.
Wow. The last thing I dealt with that was this stubborn was a three-year-old.
Could you come up with a minimal example that shows the behavior? In particular I’m curious what the object names (not printed names) of the papers are, 'cause those are the basis for the defaults for understanding. Taking would work as you want with just this:
Lab is a room.
blue paper is in lab.
player carries red paper.
'cause there’s already this in the Standard Rules:
Does the player mean taking something which is carried by the player
(this is the very unlikely to mean taking what's already carried rule):
it is very unlikely.
So something about your code is different. (examine paper in this case would examine the carried paper without disambiguation, though.)
Aha. I have a strange and unwise attraction to that very bad boy of Inform 7: “instead of”.
I had an “instead of” rule that I wisely changed to a “check” rule, but failed to take out the “if the player carries the paper” that made the instead rule work as I needed. It sucks to have such a reflexive tendency to use the very thing that will always, ALWAYS cause me grief. Got it fixed now.
Nothing to see here, folks. Move along from the train wreck.
ETA: well, crap. Not fixed. I think I probably need to revisit basic rules for changing text when taking or examining something. This is a whole lot of stupid.
There’s an undocumented thing with examining rules that I’ll mention in case it’s involved: the examining action has a truth state called examine text printed. The most general (and thus expected to always be last) carry out examining rule says “You see nothing special about [noun]” only if there’s been no output yet, i.e., examine text printed is false. So any author-created examining rule that outputs anything should set examine text printed to true or you’ll get “You see nothing special” as bonus output.
In my experience, Inform’s preference for the thing you’re holding is not worth trying to undo. It’s easier to go around.
Here’s a demo that mostly does what you (Amanda) want, I think. This mechanism favours bits of paper that haven’t previously been read (examined) when you’re examining. I’ve simulated the fact that the player has already read paper(1) earlier in the game by setting it to ‘examined’ when the demo starts. So your first examine in the demo will look at the one on the floor. But if you examine again straight away, it reverts to the one you’re carrying by default, because now they’ve both been read, and it loves the one you’re carrying… and it still prints the clarification message with the paper’s name, so the player will get a nudge to specify the one on the floor if they insist on re-examining this bit of paper on the floor without picking it up first.
The fewer DTPMs are involved, the less chance we have of messing up other default behaviours.
The only thing I haven’t done (which I should) is alter the names of the papers slightly. One could be crinkled, one could be ‘a sheet’, etc. This is required for general sanity in life. But in this demo, the bit of paper on the floor prints with a (2) after it, the one you start holding has a (1).
(If you already have an ‘examined/unexamined’ type flag on all objects in your game, use that instead of the one I introduce in this demo.)
The Arena of Frequent And Bloody Conflict is a room.
a thing can be examined or unexamined.
a paper is a kind of thing.
Understand "piece/paper", "piece of paper" as a paper.
[I don't want to use this, but you might want it later or someday: The printed name of a piece of paper is usually "piece of paper".]
Last carry out examining:
now the noun is examined;
Does the player mean examining an unexamined paper:
it is very likely;
a paper1 is a paper.
the printed name of paper1 is "piece of paper(1)".
player holds paper1. paper1 is examined.
a paper2 is a paper in the arena.
the printed name of paper2 is "piece of paper(2)".
Test me with "i/x paper/x paper/x paper/x paper2/drop paper/x paper/paper1/get paper/paper1/get paper/drop paper/paper2/drop paper".
Oh hang on, have I written a demo actually doing the reverse of what you want? Sorry
Your initially described situation is weird, because it’s the reverse of the norm. That’s why you’d normally need to do something like my demo to change it. Uh, yeah I think you’ve already tilted rules or DTPMs somehow to bring it about.
@AmandaB Okay, so re-reading this very complex topic, I see you ultimately might want the demo I wrote, after undoing some other stuff.
As an approach, I’d reiterate what Mike said, but a bit more directly – the parser does not want to disambiguate. It uses scores (set by internal rules and DTPMs) to try to pick something. Only if it can’t decide, then it will take all the choices it considered and throw them into a relevant disambiguation question. So trying to force disambiguation questions in particular circumstances can work, but if you try to broaden it to wider contexts, it becomes a fight with the system.
Here’s something I noticed about lots of your DTPMs: They’re 'doing something’s. That is a wide definition. Try making them more specific whenever it’s possible. Does the player mean taking… does the player mean examining… etc. Then fewer other rules and actions can be affected. I know in your case you were trying to throw the net wide for all the papers, but my advice is for using DTPMs in general. You want to use the fewest, smallest and most minimum you can get away with to make what you want to happen happen.
So that rule you’ve got that’s caused this whole business with the paper, it’s fighting default behaviour all over the place. I would definitely cut that and try some more specific DTPM rules (does the player mean sitting… does the player mean entering… blah blah blah) … and/or look at the rule that decides what the default is going to be in the first place. I see this in the Standard Rules:
Rule for supplying a missing noun while entering (this is the find what to enter
if something enterable (called the box) is in the location,
now the noun is the box;
otherwise continue the activity.
Sitting is a kind of entering (I was reminded of this just by seeing it nearby in the Standard Rules. I didn’t remember that off the top of my head.)
And after all that, return to the pieces of paper. And maybe at that point my ‘examining unread stuff first’ demo for papers might be of use.
Thanks, Wade. I have definitely also done something funky somewhere else that’s causing problems, and the bigger problem is really that I’m behind the curve with understanding inventory and disambiguation. My first game didn’t have inventory, and the second one didn’t need to mess with the basic TAKE. In this one, I need to do fancier stuff, like auto-reading a piece of paper on taking it. So I’m still struggling with how messing with TAKE affects downstream actions. “Behind in the basics” could be my motto for most things.
And yes, the demo is useful. Since ParserComp due date is in one week, I may have to settle for an ugly solution, as I don’t want to disrupt the Jenga tower too much, but then I’m going to set myself some lessons to start actually understanding what’s going on instead of flailing.
And I have learned my lesson about multiples. Never again.