Lost Items

I’m thinking about writing an extension.

It will be similar to Aaron Reed’s “Remembering,” and hopefully compatible with it.

Here’s the basic idea:

Sometimes things in the game might disappear. In the case of my WIP, this will happen during flashbacks. They could also happen when the player changes to a different person, or an unusual effect causes an item to be lost (perhaps a pickpocket will take something from your inventory). We want the game to respond with something more helpful than “You can’t see any such thing.”

Remembering might work for this, but it only works for taking, dropping, and examining. “Buy the hen with the gold coin” won’t work if the coin’s been stolen from your person, and “ask Harold about Maude” won’t work if Harold just jumped off the cliff. I want something that will work for ANY verb.

I am considering two approaches:

  1. Add all lost items to the scope of the player, but fight like hell to keep them out of disambiguation.

  2. Follow a Smarter Parser-like approach, and don’t even include them in scope until we’re about to print a parser error.

I think I can get a start on #1, but I’ve had so much trouble with disambiguation that I want to address that issue first. I can never seem to get “Does the player mean” or even Disambiguation Control to really do what I want. Even if I make “doing something with the bread” very likely and “doing something with the bread knife” very unlikely (not a real example), it seems like I still get a disambiguation question. So I’m nervous about adding all the lost things to scope for every command. In fact, just as there is an option in Remembering to NEVER disambiguate, I want to never offer a lost item as a disambiguation choice.

#2 is looking attractive, but Smarter Parser uses indexed text, which I’m still trying to avoid. Plus, my game so far has no need for glulx and it would be nice if it were mobile-friendly.

Any advice on which path to follow, or tips on how to implement either one?

Thanks.

I’d say #2 is the way to go, especially if you want small memory footprint. #1 adds a lot of complicated code, which uses up a lot of memory, too. #2 in only adds another string->object number mapping table and only a small code piece which does the mapping. I don’t think there would be ever a game which has more than some dozen of objects which may become “unavailable”, so a plain table should be fast enough.

Well, I ran into something similar a while ago. In a nutshell: the player has, at the beginning, four ropes that he can loose. I wanted the game to respond to a lost rope with something other than “You can’t see…”, so I ended up creating the “ghost thing”.

In general terms, it was something like this (outta memory):

[code]A thing can be real or ghost. A thing is usually real.
[edited to “real”… I wrote “ghost” by mistake.]

A ghost thing is usually undescribed.

Instead of doing something to a ghost thing:
say “That was a nice [noun], but it’s gone now.”

Does the player mean doing something to a real thing: it is very likely.
[this takes care of the disambiguation problems]

[Example game]
Gallery is a room.

The red stone is a real thing in the gallery.

The green stone is a ghost thing in the gallery.

Test stone with “x stone/x green/x red”[/code]

You can then make things be real or ghost on demand, and you can make a whole bunch of rules for ghost things (not showing up in descriptions, inventory, etc.)

I don’t know Inform well enough to tell you how will this behave regarding memory, though.

Is there some way to invoke the name-parsing power of Inform there? I’m going to have at least a dozen objects, and I don’t want to duplicate the parsing of their names for both cases when they’re present and when they’re absent.

I tried #1 briefly, but unfortunately it only works for verbs that take a visible noun. The touchable requirement seems to produce a stock error before my Instead rule ever gets a chance (printing “That isn’t available.”)

How about something like this (an imperfect solution):

Rule for printing a parser error when the latest parser error is the can't see any such thing error and the player's command includes "[any ghost thing]": say "That was a nice [matched text], but it's gone now."
(This assumes that the ghost thing is not in scope anymore.)

You could use the ghost approach and move the object to the player’s possessions as it becomes ghost. Then it’s just a case of changing inventory listing so that ghosts don’t show. That way the object is yours, anywhere, anytime - darn, this sounded so much like a radio commercial.

The plus side of this approach is you don’t have to mind scope, tables or indexed text and the ghost object ends up answering to any command, just as a normal object would. The minus side is you have a problem with ghost NPCs, but you can work around that by switching from a John person to a John thing and move it to the player.

What’s imperfect about about that? That looks like exactly what I need.

That’s like what I was doing before. I had a container called “your memory” which was part of the player. It might also work as a backdrop. When doing it that way, you don’t even have to hide anything. It even worked for NPCs. But it does have the potential for weird interactions.

I thought it needed a disclaimer because you need to tweak it to prevent, for example, the following more or less fringe cases:

In fact I’m usually extremely cautious about using user input as such in the output. It’d be better to loop through every ghost thing and check if it’s mentioned in the player’s input, but frankly I don’t know how to implement that (you can’t use variables as grammar tokens).

Actually it would be awesome if someone would make an extension that could do something like this:

if the parser would understand the command "foo bar": ... if the parser error for the command "foo bar" would be the can't see any such thing error: ... Parse the command "foo bar". if the verb "foo" is in the dictionary: ... if the noun "foo" is in the dictionary: ...
And I would kill for:

repeat with X running through things in the location: if "foo" is understood as the name of X: say "[X] is what you're looking for."

This is a brute-force approach that I haven’t tried, but would it be possible to do something along these lines? You create a “tag [any thing in location]” action that actually only sets a global truth state (true if the thing understood is found, false otherwise). The action is out-of-world. Then, you pipe that through “the player’s command” and “try” it in sequence.

I have no idea how fast it would be, or even if it’s deeply stupid. The thought of trying it frightens me.

Thank you Eleas and Juhana! You have helped me frame the problem and I have solved it:

[code]The item sought is a thing that varies.
Definition: A thing is sought if it is the item sought.

Rule for printing a parser error when the latest parser error is the can’t see any such thing error and the player’s command includes “[any lost thing]”:
Repeat with the missing item running through lost things:
Now the item sought is the missing item;
if the player’s command includes “[any sought thing]”:
abide by the notice absence rules for the missing item;
make no decision;[/code]

I leave it as an exercise to the reader to apply the “sought item” trick to a more generic understanding rulebook.

Curious, though - now I’m getting “that noun did not make sense in this context” when I should be getting “you can’t see any such thing.” Why would that be?

Commenting out the rule for printing a parser error restores the proper message, even though according to this, the rule never applied. Twice.

I’ve tried figuring out how to hack this to print the appropriate library message. I could cheat and just say “You can’t see any such thing,” but I want to be compatible with Custom Library Messages. But I can’t figure out how to issue a library message that isn’t associated with an action. There seems to be some I6 voodoo going on.

It looks like you’re instructing your parser error rule to make a decision based on what the absence rules decide (“abide by”), but aren’t actually deciding anything there. Add something like this to your absence rules definition and the problem will go away:

The notice absence rules have outcomes end (success - the default) and continue (no outcome).

Alternatively, end each of your notice absence rules with “rule succeeds” or “rule fails”.

–Erik

I’ve written an ugly hack for getting around the “you can’t see any such thing” message problem. Here is the full text of my extension. I’d love to hear your comments:

[spoiler][code]Lost Items by Mike Ciul begins here.

Include Epistemology by Eric Eve.

Book 1 - Lost

Chapter 1 - Definition of lost

A thing can be lost.

Chapter 2 - Losing things

To lose (the item - a thing):
Remove the item from play;
Now the item is lost;

To abduct (the item - a thing) to (the prison - an object):
Now the prison holds the item;
Now the item is lost;

Chapter 3 - Finding things

To return (the item - a thing) to (the haven - an object):
Now the haven holds the item;
Now the item is not lost;

To put (the item - a thing) back on (the wearer - a person):
Now the wearer wears the item;
Now the item is not lost;

Book 2 - Familiarity

Chapter 1 - Basic Familiarity (in place of Chapter 1 - Basic Familiarity in Epistemology by Eric Eve)

A thing can be familiar or unfamiliar. A thing is usually unfamiliar.

Carry out examining something visible (this is the mark items as seen on examining rule):
now the noun is familiar;
now the noun is seen.

Definition: a thing is known if it is familiar or it is seen or it is lost.

Definition: a thing is unknown if it is not known.

Book 3 - Remembering lost things

Chapter 1 - The Notice Absence rulebook

Notice absence is an object-based rulebook with default failure.

Notice absence of something (called the missing item) (this is the default notice absence rule):
say “That’s odd. [The missing item] doesn’t seem to be here anymore.”

Chapter 2 - When to notice absence

The item sought is a thing that varies.
Definition: A thing is sought if it is the item sought.

Rule for printing a parser error when the latest parser error is the can’t see any such thing error:
Repeat with the missing item running through lost things:
Now the item sought is the missing item;
if the player’s command includes “[any sought thing]”:
abide by the notice absence rules for the missing item;
say “[you can’t see any such thing]”;

Chapter 3 - Dirty hack for You can’t see any such thing message

Section 1 - Simple Hack (for use without Custom Library Messages by David Fisher)

To say you can’t see any such thing:
say “You can’t see any such thing.”

Section 2 - Library Messages Table Hack (for use with Custom Library Messages by David Fisher)

To say you can’t see any such thing:
display LibMsg

Lost Items ends here.[/code][/spoiler]

I have a better fix now. I think the problem is when you put an “[any X]” token in a match against the player’s command, the value of the latest parser error gets changed as a side effect. So I just reset the value before exiting the rule:

Rule for printing a parser error when the latest parser error is the can't see any such thing error: Repeat with the missing item running through lost things: Now the item sought is the missing item; if the player's command includes "[any sought thing]": abide by the notice absence rules for the missing item; now the latest parser error is the can't see any such thing error; make no decision;

A clear case against global variables, I think.