Pushing item locations in Casting SPELs
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 cons
es 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?
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.
精彩评论