Main      Site Guide    
Smash Tutorial

Example: Picking Up an Object


Picking up objects is a very common thing to do in adventure games, and it involves more than just popping the item into your inventory. There are a couple ways to do this, each with their own strengths and weaknesses. Be careful, because you can get yourself into trouble if you use the wrong one. We will discuss several methods of doing this here.

Let's start with the most obvious and intuitive method:

c d:sponge * take Take the sponge. p Ok. You have the sponge. a sponge

In the above code, the "take" option is only provided if you don't already have it. If you do, and the user selects it, then it will be added to your inventory. However, there is a major drawback here, and that is, what if the sponge is lost somewhere else along the way? Suppose you could feed the sponge to a monster who would eat it all up? Then you'd no longer have it. But that would mean that when you come back to this location, you'll be able to "take the sponge" again.

So the above code only works in two situations: (1) if you will never ever lose the object, or (2) if there is an unlimited supply of the objects (a big heaping pile of sponges), and you are permitted to take one at a time.

An alternative, with the same drawbacks, follows:

* take Take the sponge. c a:sponge p You already have the sponge! C p Ok. You have the sponge. a sponge

The above example is the same as the first, except that the "take" option is present at all times, and you simply get an error message if you try to take it when you already have it. This option works but probably isn't a good idea except in the situation that there is actually an unlimited supply of sponges instead of just one. (Then, if you tried to take one and already had one, the error message could be something on the order of, "You already have a sponge," or "You don't need to take more than one.")

Before we get to solving the drawbacks of these two examples, there's the issue of the area description text to consider. Usually if there is an option available for the taking, the description of the area will mention it. In the "heaping pile of sponges" scenario, this is easy. You simply have your area description text say, "There is a heaping pile of sponges here," and that's it. But if there is only one sponge, you don't want to say, "There is a sponge here," when there isn't. The code below is a modification of the first example that shows how to set the area description text properly.

. It is a dark and stormy night. c d:sponge , There is a sponge here. * take Take the sponge. p Ok. You have the sponge. a sponge

And here is how you do this with the second example:

* take Take the sponge. c a:sponge p You already have the sponge! c d:sponge p Ok. You have the sponge. a sponge . It is a dark and stormy night. c d:sponge , There is a sponge here.

(Above, the area description code could just as easily have come before the option as after it.)

Now let's address the issue raised before. What if the sponge can be "lost" to the player? What if it can be traded or stolen or given away? The code has to make sure the player can't come back and get another sponge.

We can solve this problem by using a variable (usually a state variable, but a global would also work) to keep track of whether the sponge has ever been picked up. If it's been picked up before, the user shouldn't be allowed to pick it up again whether he has the sponge at present or not.

. It is a dark and stormy night. c took_sponge = 0 , There is a sponge here. * take Take the sponge. p Ok. You have the sponge. a sponge s took_sponge = 1

Above, the state variable took_sponge is 0 when the player has never picked the object up before, and 1 when the player has. If the player loses the object later, took_sponge will retain its value of 1, and picking up the object a second time won't be permitted, because the option to do so won't ever show up.

Note that this code still works even if it is not possible to "lose" the sponge. Therefore it is recommended that this method be used for all situations (except the "heaping pile of sponges" scenario, where the example just before this one works well).

Here is the same example as above, but with a "drop" option. Normally you wouldn't need to have a drop option, but once in a while it's useful:

. It is a dark and stormy night. c took_sponge c a:sponge * drop Drop the sponge. p Ok. You dropped the sponge. d sponge s took_sponge = 0 C , There is a sponge here. * take Take the sponge. p Ok. You have the sponge. a sponge s took_sponge = 1

When you drop the sponge at this location, the sponge becomes available for the taking again. Therefore, took_sponge is reset to 0 to permit that. If the sponge is lost in any other fashion, the state variable should not be reset, because you don't want the "take" option to be become available again.