Problem with substituting take for buy

I have the following. It substitutes buy for take fine for first time, but then returns ‘Nothing is on sale’ for everytime afterwards. Taking first time and each time after works fine.

My code:

instead of taking sunglasses1 for first time:
Move sunglasses to player;
Say “You pick up a pair of [’]Bay-Rans[’] and pay the stall holder with your credit card.”

Instead of taking sunglasses1:
Say “You already have some.”

Instead of buying sunglasses1 for first time:
try taking sunglasses1

Instead of buying sunglasses1:
Say “You already have some.”

Game response:

buy sunglasses
You pick up a pair of ‘Bay-Rans’ and pay the stall holder with your credit card.

buy sunglasses
Nothing is on sale.

works as intended if i just make a room and sunglasses and copy/paste your code.

Where in your code is “nothing is on sale” coming from?
That would be where i would look to see why it’s overriding your insteads.

The “for the first time” phrase only applies to the first attempt to perform a given action. You have two different actions in play, the taking action and the buying action.

Your general “instead of buying” rule only reroutes to a taking action on the first attempt. You might find it easiest to just always reroute the buying action to a taking action for the sunglasses, so that the taking-related rules will always apply.

Instead of buying sunglasses1:
    try taking the noun instead.

However, there are other problems waiting for you with your current approach. You might be better off with a different approach. Here’s a simple one:

"Sunglasses for Sale"

Place is a room.

Some sunglasses are in Place.

The block buying rule does nothing when the noun is the sunglasses and we have not bought the sunglasses. [See WWI 19.5 Changing the behavior of rules. You can use the >ACTIONS debugging verb to help identify the actions being triggered and rules producing responses; see WWI 24 Testing and Debugging. Also see WWI 9.12 Actions as conditions.]

Instead of buying sunglasses when we have bought the sunglasses:
	say "You already paid for those!"

After buying sunglasses when we have not bought the sunglasses: [See WWI 7.5 After rules.]
	move sunglasses to player;
	say “You pick up a pair of [’]Bay-Rans[’] and pay the stall holder with your credit card.”

Instead of taking sunglasses when we have not bought the sunglasses:
	try buying the sunglasses instead.

If there are many things to buy, you would want to generalize the above.

2 Likes

Otistdog- I’d agree with your reservations about the general approach to coding this scenario, but ManchurianMan called it right re the problem with the code as written- it should (and indeed does) work with the general ‘instead of buying’ rule taking over after the first attempt at buying: the problem is interference from elsewhere that is preventing the general ‘instead of buying rule’ from running.

Necrodeath- typing ‘actions’ and/or ‘rules’ before testing your story should help indicate which action/rule is interfering with your buying action.

PS as an aside, rather than moving things direct to the player in new or newly enabled actions, it’s generally better form if possible to route things through ‘try silently taking’ to ensure that the attempt to acquire something passes all the sanity checks usually applied to the taking action, including enforcing touchability, carrying capacity, automatic use of the player’s holdall and many more besides (see the Index under Actions), then afterwards check that taking has been successful:

e.g. in this instance

Instead of buying:
	try silently taking the noun;
	if the player holds the noun:
		say “You pick up [a noun] and pay the stall holder with your credit card.”;
	else:
		say "None seem to be available.".

If you’re moving something from off-stage to the player, you can move it temporarily to the location before trying to silently take it, then move it back off-stage if taking is unsuccessful.

@drpeterbates, I had missed that there were two different objects in the original code.

The two things “sunglasses” and “sunglasses1” are indistinguishable when typed because both exceed 9 letters (the default maximum recognizable word length for the parser).

After the player has the sunglasses (from off-stage?), that object is the one chosen by default for a buying action (without a disambiguation message). No rule in the original code covers the sunglasses, so the default block buying rule applies. That’s where the message cited as a problem comes from. The following test me illustrates the difference.

"Sunglasses Redux"

Place is a room.

Other Place is east of Place.

There are some sunglasses.

Sunglasses1 is in Place.

instead of taking sunglasses1 for first time:
    Move sunglasses to player;
    Say “You pick up a pair of [’]Bay-Rans[’] and pay the stall holder with your credit card.”

Instead of taking sunglasses1:
    Say “You already have some.”

Instead of buying sunglasses1 for first time:
    try taking sunglasses1.

Instead of buying sunglasses1:
    Say “You already have some.”

Test me with "buy sunglasses / g / e / drop / w / buy sunglasses".

@necrodeath, what is the purpose of sunglasses1? Is it supposed to be a display rack of sunglasses or the like? If the previous suggestion doesn’t help you get the effect that you wanted, then posting a longer excerpt of your code would make it easier to assist. (Also, FYI – you can mark the code excerpts as code with the “</>” icon in the editor window. Alternatively, lines are assumed to be code if they start with a tab.)

1 Like

Ah. That makes sense. I had assumed it was a typo. Although it makes less sense that Inform would prefer a carried item to an item in the location in deciding how to disambiguate ‘sunglasse’ for the action of buying. Clearly it ignores the ‘carried’ status and makes a default choice of a handled item.

So, the problem can be fixed by adding:

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

Thanks all.

What I’m trying to do is the following:

There is a street stall (supporter) that sells sunglasses.
I want the player to be able to take or buy the sunglasses (once), but for the scenery sunglasses to still be on the stall afterwards (instead of doing the ‘you buy the last pair’ trick.

There is no buying and selling elsewhere in the game so the whole ‘nickel and dime’ would be overkill - hence the players carries a credit card.

I didn’t know that 9 letters was the limit for the parser - good to know!

Edit: Peter’s solution solves it for me: ```
Does the player mean buying something which is enclosed by the player: it is very unlikely.

Two other things worth knowing-

(i) If compiling for Z-machine, sometimes it’s not even 9 letters: Words in the dictionary Inform uses to look up typed-in words are in the Z-machine stored in a compressed form that uses more space for some unusual letters (e.g. some accented characters) or punctuation than for standard a->z letters. If you have things named using these unusual letters the limit for distinguishing words starting in a similar way will be less than 9 letters. This does not apply to Glulx, which uses the same space in the dictionary for any character.

(ii) For Glulx only, if this becomes an intractable issue you can increase the number of letters Inform uses to store dictionary words by redefining the constant DICT_WORD_SIZE, which is usually 9 by default- e.g.

Use DICT_WORD_SIZE of 15.

The maximum size of dictionary words in the Z-machine cannot be altered.

You may still have problems if you immediately drop the sunglasses then try to buy some more, as Inform will then again assume you’re buying sunglasses instead of sunglasses1. If this is the only sale you have going on, you’d be better with:

Does the player mean buying sunglasses1: it is very likely

which means that for buying sunglasses1 is always preferred when sunglasses1 and sunglasses are both in the location. For taking, sunglasses will by default be preferred because sunglasses1 is scenery.

This example makes use of conditional understanding to avoid having to apply any “does the player mean...” rules.

The display will persist as an item in the room but only be responsive to the word “sunglasses” when the pair of sunglasses isn’t around. Attempts to buy the pair of sunglasses are routed to the display whenever the display is in view.

"Sunglasses for Sale"

Place is a room.

The player carries a credit card.

A kiosk is a fixed in place supporter in Place. "A display kiosk is here, featuring many pairs of sunglasses. Some are quite stylish." Understand "display" as the kiosk. Understand "sunglasses" as the kiosk when the player cannot see the sunglasses. [see WWI 17.17 Context: understanding when]

There is a thing called your new sunglasses. They are wearable and plural-named.

Instead of buying the sunglasses when the player can see the kiosk:
    try buying the kiosk instead.

Instead of taking the kiosk:
    try buying the kiosk instead.

The block buying rule does nothing when the noun is the kiosk.

Instead of buying the kiosk when we have bought the kiosk:
    say "What happened to the pair that you already bought?"

Check buying the kiosk when the player does not carry the credit card:
    say "You'll need your credit card for that." instead.

After buying the kiosk:
    now the sunglasses are on the kiosk; [using drpeterbatesuk's suggested style here]
    silently try taking the sunglasses;
    if the player carries the sunglasses:
	    now the player wears the sunglasses;
	    say "You select a pair that appeals to you and hand over your credit card. After a quick swipe and authorization, you put them on. Nice.";
    otherwise:
	    say "You pick out a pair that appeals to you, and quickly pay for them."

Test me with "drop card / take sunglasses / get card / buy sunglasses / x sunglasses / buy sunglasses / drop sunglasses / take sunglasses".

That’s neat!

However…
You have an incorrect response to a failure to take the sunglasses and haven’t moved them back out-of-play :wink:

Although, I suppose it’s not unreasonable to leave the untaken sunglasses on the kiosk to be taken later, assuming they’ve now been paid for, which on closer consideration seems to be the intention of your code :+1:t2: Perhaps that would ideally be signposted in the response, e.g.

say “You pick out a pair that appeals to you, and quickly pay for them. All that remains to achieve the height of cool is to take them from the kiosk and put them on.”