Picking Up Objects

Next, let’s create a command to pick up objects in our world. To do so, we modify the variable *object-locations* that we’re using to track the location of objects:

(defun pickup (object)
  (cond ((member object
                 (objects-at *location* *objects* *object-locations*))
         (push (list object 'body) *object-locations*)
           `(you are now carrying the ,object))
          (t '(you cannot get that.))))

The pickup function uses the member function to see if the object is indeed on the floor of the current location. (The member function checks to see if a particular item is found in a list of items.) We use the objects-at command to generate the lists of objects at the current location.

If the object is at the current location, we use the push command to push a new item onto the *object-locations* list, consisting of the item and its new location. The new location will just be body, for the player’s body.

The push command simply adds a new item to the front of a list variable’s list. For example, the following example adds the number 7 to the list 1 2 3:

> (defparameter *foo* '(1 2 3))
*FOO*
> (push 7 *foo*)
(7 1 2 3)
> *foo*
(7 1 2 3)

This push command is basically a convenience function built on top of setf. For example, we could have replaced the preceding push command with (setf *foo* (cons 7 *foo*)) and obtained the same result. It’s just easier to use push.

Pushing a new location for an object onto our *object-locations* alist does seem a bit odd. Since we’re never removing old locations for objects, just pushing new ones, it means that *object-locations* may contain multiple entries for a single object, and that this list now has two stored locations for the object in question. Fortunately, the assoc command, which we use to find objects in a given location (within the objects-at command), always returns the first item it finds in a list. Therefore, using the push command makes the assoc command behave as if the value in the list for a given key has been replaced altogether.

Using the push and assoc commands together in this way allows us to pretend that values in an alist are changing, while still preserving old values. Old values are simply suppressed by newer values, thus preserving a history of all old values. The push/assoc idiom is a common technique used by Lispers.

Now let’s walk back to the living room and try to pick up an object:

> (walk 'east)
(YOU ARE IN THE LIVING-ROOM OF A WIZARDS HOUSE. THERE IS A WIZARD SNORING
 LOUDLY ON THE COUCH. THERE IS A DOOR GOING WEST FROM HERE. THERE IS A LADDER
 GOING UPSTAIRS FROM HERE. YOU SEE A WHISKEY ON THE FLOOR. YOU SEE A BUCKET ON
 THE FLOOR.)
> (pickup 'whiskey)
(YOU ARE NOW CARRYING THE WHISKEY)

It worked. We’re carrying the whiskey, which means that we can now pick up things in our world!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.93.12