Pushing item locations in Casting SPELs

153 views Asked by At

I'm going through Casting SPELs in Lisp and this is the proposed solution to handling picking up objects:

(define *location* 'living-room)

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

(define (pickup-object object)
  (cond [(is-at? object *location* *object-locations*)
         (push! (list object 'body) *object-locations*)
         (string-append "You're now carrying the " (symbol->string object) ".")]
        [else "There's no such object in here."]))

Am I the only one who finds this inefficient? As far as I understand the push! function conses a new pair to *object-locations* every time the player picks up an object. While this may not be a major problem in a small game like this, if one would to add the option of putting down items from the inventory, the *object-locations* list could grow infinitely... Shouldn't pickup-object replace the cdr of (whiskey-bottle living-room), for example, instead of adding another copy of the pair?

I'm new to Lisp and may be mistaken... Could somebody please explain whether my assumptions are right, and if so, what would be the best way to handle picking up of objects in a Lisp text adventure?

1

There are 1 answers

4
Rainer Joswig On BEST ANSWER

There are a few problems with the code:

  • The list *object-locations* is a literal. Literals should not be modified. You can't change the location of frog destructively. So you need to push a new location in front.
  • The list grows as you walk through the game.
  • STRING-APPEND creates a new string for each pickup action.

But

  • It is simple and sufficient for a book example.
  • The stack for object locations would make some kind of undo possible.
  • The push of a new association of item and location is a fast operation.
  • It leaves the opportunity for the reader of the book to make the code more efficient.

In Common Lisp that's easy to change:

(defvar *object-locations*
  (copy-tree
   '((whiskey-bottle living-room)
     (bucket living-room)
     (chain garden)
     (frog garden))))

(defun get-location (object)
  (second (assoc object *object-locations*)))

(defun set-location (object location)
  (setf (second (assoc object *object-locations*))
        location))

CL-USER > (get-location 'frog)
GARDEN

CL-USER > (set-location 'frog 'living-room)
LIVING-ROOM

CL-USER > (get-location 'frog)
LIVING-ROOM

CL-USER > *object-locations*
((WHISKEY-BOTTLE LIVING-ROOM)
 (BUCKET LIVING-ROOM)
 (CHAIN GARDEN)
 (FROG LIVING-ROOM))

See the book Common Lisp: A Gentle Introduction to Symbolic Computation by David S. Touretzky for a really basic introduction to Lisp.