Describing Objects at a Specific Location

To create the final piece of code to help us visualize our game world, we need to describe the objects on the floor at a given location, which a player can pick up and use.

Listing Visible Objects

To do so, we first create a list of the objects:

> (defparameter *objects* '(whiskey bucket frog chain))
*OBJECTS*
image with no caption

We can also create a second variable, *object-locations*, to track the location of each object in the form of an alist:

(defparameter *object-locations* '((whiskey living-room)
                                   (bucket living-room)
                                   (chain garden)
                                   (frog garden)))

Next, we write a function that lists the objects visible from a given location:

(defun objects-at (loc objs obj-locs)
   (labels ((at-loc-p (obj)
              (eq (cadr (assoc obj obj-locs)) loc)))
     (remove-if-not #'at-loc-p objs)))

This objects-at function declares a new function named at-loc-p using the labels command . (Remember that the labels function allows you to define functions locally.) Since the at-loc-p function won’t be used elsewhere, we can just declare it directly within objects-at, hiding it from the rest of the code in our program.

The at-loc-p function takes the symbol for an object and returns t or nil, depending on whether that object exists at the location loc. It does this by looking up the object in the obj-locs alist. Then, it uses eq to see whether the location it finds matches the location in question .

Why did we name this function at-loc-p? When a function returns nil or a truth value, it’s a Common Lisp convention to append a p to the end of that function’s name. For instance, you can check that the number 5 is odd by calling (oddp 5). Such true/false functions are called predicates, which is why we use the letter p.

The remove-if-not function in the last line of the listing , as you might expect, removes all things from a list for which a passed-in function (in this case, at-loc-p) doesn’t return true. Essentially, it returns a filtered list of objects consisting of those items for which at-loc-p is true.

Here’s what object-at looks like in action:

> (objects-at 'living-room *objects* *object-locations*)
(WHISKEY BUCKET)

Describing Visible Objects

Now we can write a function to describe the objects visible at a given location:

(defun describe-objects (loc objs obj-loc)
  (labels ((describe-obj (obj)
               `(you see a ,obj on the floor.)))
    (apply #'append (mapcar #'describe-obj (objects-at loc objs obj-loc)))))

In this listing, describe-objects first creates the describe-obj function . This function generates a pretty sentence stating that a given object is on the floor, using quasiquoting . The main part of the function consists of calling objects-at to find the objects at the current location, mapping describe-obj across this list of objects, and finally appending the descriptions into a single list .

Let’s try running describe-objects:

> (describe-objects 'living-room *objects* *object-locations*)
(YOU SEE A WHISKEY ON THE FLOOR. YOU SEE A BUCKET ON THE FLOOR)

Perfect!

image with no caption
..................Content has been hidden....................

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