searching containers

I have three showcases (containers) in my room. If the player says something like BUY TORCH, I want the player to get that torch with money extracted. However, I don’t know what showcase it is in with the action ‘BUY (something)’. I want to search each showcase until I find it. If I don’t I send a out-of-stock message.
However, my if N contains Item: doesn’t seem to be working. I’ve tried lots of different permutations and the Item is never found. I thought this was the proper syntax to search a container.
The code below searches through all the showcases but never finds the item. How should I search a series of showcases?

[Buy selected item from selected showcase]
The null showcase is a showcase. 
CurrentCase is a container that varies. CurrentCase is the null showcase.

[The item must exist in showcase and player must have enough money for it.]
Check buying something when location is Emporium:
	search for noun;
	let C be ChrCostBuying for cost of noun;
	say " 'That [noun] costs [cost of noun to 1 decimal places] gp...' ";
	say "but for you, I'll let you have it for [C to 1 decimal places] gp.[line break]";

[Search the showcases for the item to be purchased.]
to search for (Item - equipment):
	let L be {Weapons showcase, Armor showcase, Outfitting showcase};
	repeat with N running through L:
		say "Searching [N] for [Item][line break]";
		if N contains Item:
			now currentCase is N;
			say "CurrentCase = [currentCase][line break]";
			break;
	if currentCase is the null showcase:
		say "Ganon shakes his head and says, 'Sorry, I don't have any now.' ";

Notice that if I find the item, I set currentCase to the showcase containing it for the BUYING action to work on it. The variable currentCase is declared outside any rule, so it is not temporary.

In the buying action you can check the holder of the noun, which should tell you what container it is in.

If you have previously defined a showcase as a kind of container, you could check the presence of the item like this, for example:

Check buying something when the location is the Emporium:
	if the noun is in a showcase in the Emporium:
		say " 'That [noun] costs [cost of noun to 1 decimal places] gp...'";
	else:
		say "Ganon shakes his head and says, 'Sorry, I don't have any now.'";
		stop the action;

Having said that, your code above should work too, if the noun is indeed in one of the showcases. (Though the code as given seems to be missing some bits of the framework around it, so it’s difficult to be completely sure what’s going on.)

In such cases, you could always try to check the location of items with the SHOWME command and/or the World Index in the IDE.

If you do need to refer to the actual showcase which the noun is in, you can use the holder of the noun (see ch. 8.17 in the docs), as A J Mako said.

As a side note, if the player wants to buy something that’s not in the location at all at the moment, you’ll get the parser error “You can’t see any such thing” instead of Ganon’s response. (Because, by default, the buying action applies to one thing, that is, one touchable thing.)

Thanks for this. Questions:

Inform knows to check all the showcases in the room? I don’t have to designate which one?

Yes, the showme command works for the noun, but it doesn’t apply to actions, like “BUY (something)”. I need to get the properties, like cost, of what is being bought.

Great! Sounds good. I didn’t know about that phrase.

There are a few cases where the showcase is not in the room, but belong the the player. In that case, I put that showcase in scope and it seems to work fine.

I also noted another mistake I made: I declared the currentCase as a container, not a showcase. That probably explains why something sometimes was found in “water skein” :roll_eyes:

This worked great for as far as it went. This works for anything the player is not carrying. For example, I can buy a rope but not a torch, because the player has a torch already.
If the player is carrying the noun, then it is not found in a showcase because the player is checked first. However, I want the player to be able to buy things he already has.

I would expect that

	if the noun is in a showcase in the Emporium:

would check only showcases.
I’m not sure how to say check the showcase (holder of the noun) whether the player is carrying it or not.

Here is my code. It seems that once the noun is found, it quits searching. And it searches the player (NOT A SHOWCASE) and stops.

CurrentCase is a showcase that varies. 

[The item must exist in showcase and player must have enough money for it.]
Check buying something when location is Emporium:
	say "The [noun] is in the [holder of the noun][line break]";
	if the noun is in a showcase in the Emporium:
		now the currentCase is the holder of the noun;
		let C be ChrCostBuying for cost of noun;
		say "Check buying:   CurrentCase = [currentCase][line break]";
	otherwise:
		say "Ganon shakes his head and says, 'Sorry, I don't have any now.' " instead;

Perhaps I can set a definition?

Definition: The player is not a showcase.

Really?

I dropped the torch and still a showcase search didn’t find it. Only when I put the torch out of the room did the showcases get searched and Ganon found it.

Well if the player is carrying it, the holder is the player and not the showcase. That’s probably why your original code wasn’t returning it: the moment the player picks it up, it isn’t in the showcase object.

I think there might be a miscommunication here regarding what your showcases are.

Just to clarify: when you said it searches the player, what do you mean? Printing “The [noun] is in the [holder of the noun][line break]”?

The statement is

	if the noun is in a showcase in the Emporium:

I didn’t ask for a search everywhere, just a showcase. The player is not a showcase. Why is it finding in the player and then stopping.

I think this is a bug in the phrasing because there are multiple torches. Inform assumes there is only one, which is why is quits searching. But still…the player is not a showcase. Why is it even looking there?

If I go to the index, it shows a list of torches. One torch says it is held by the player; other torches are contained in the Outfitting showcase, which is as it should be.

From my experiments, it searches in the player first, then in the room, and then in the showcases. That is the only way that other things work but not the torch, because a torch is in two places. It is exceedingly frustrating that it DOES NOT search the showcase as requested. (I even tried searching showcases by name, and it searches elsewhere first.) I think multiple objects causes the internal Inform routine to kickout.

Can you show us your output from this?

Here is the code (slightly revised to remove experiments)

Check buying something when location is Emporium:
	if the noun is in a showcase (called S) in the Emporium:
		now the currentCase is S;
		let C be ChrCostBuying for cost of noun;
		say "Check buying:   CurrentCase = [currentCase][line break]";
	otherwise:
		say "Ganon shakes his head and says, 'Sorry, I don't have any now.' " instead;

And the output. I can buy things I’m not carrying and are not in the room, like the rope.

1 Like

You need a line like this:

Does the player mean buying something which is enclosed by the player:
	it is very unlikely.

Otherwise it could happen that, when the player enters “buy torch”, that Inform thinks that he refers to a torch which he is already carrying (and then the noun will refer to that torch).

2 Likes

Yes, that is what I needed. Some way to exclude the player from the search. I’ll try that for the room also.

2 Likes

I changed the case so that it doesn’t exclude the player but includes the showcases.

Does the player mean buying something which is enclosed by a showcase:
	it is very likely.

Now the showcased torch is found whether there is another torch in the room or carried by the player.

Success!
Thank you guys all so much!

2 Likes