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!
18.191.93.12