Since I already know how to turn lead into gold, I did my wizard game (and then items) implementations before reading Land of Lisp's sections thereon, though the non-time-reversed order is advisable. Here I will compare what I did to what Land of Lisp did. We both program in a lispy way. Compare my (mapcar 'car (cddr *room*)) and the example (mapcar #'car '((foo bar) (baz qux))) or Land of Lisp's (eq (cadr (assoc obj obj-locs)) loc) to (assoc edge (cddr *room*)) And so forth. The biggest difference, already visible above is that I decided to use a circular list where the head of the single special list is the current location, and the details of each location are all literally at that location, whereas Land of Lisp used multiple special lists with #'ASSOC in a relational way. Relational means that I can get a key from list-1 that can be used to #'ASSOC an item in list-2. (Imagine join(1) in shell, or mariadb / sqlite). My single-list advantage is that we can inspect the (sufficiently small) world, or just nearby entries of a larger world > *ROOMS* #1=(CURRENT (LIVING-ROOM LAMP) (LADDER (ATTIC APPLE ORANGE) #1#) (DOOR (GARDEN) #1#)) and lexically reason that (cdadr *rooms*) will be a SETFable reference to the list that is the items at the current location, (LAMP) in this case and that (caadr *rooms*) is the name of the current location. symmetrically I think it's clear to work out what (assoc 'door (cddr *rooms*)) is going to return. On the other hand this also constrains me to not making references that reach too far or would be hard to work out. In Common Lisp, only up to 4 Ds and As come as built-in functions. (cddddr '(1 2 3 4 5)) -> (5) but #'cdddddr is not defined. On the other hand, the relational approach doesn't quickly run out of As and Ds to relate connected list items (or involve writing a reader macro for run-length-encoded #{c2a3d4adr list} which while cool might not be socially acceptable in all contexts). Since #'assoc stops at the first match, it also creates a natural history of item locations like ``` (setq *items* '((whiskey . jar))) ((WHISKEY . JAR)) (push '(whiskey . player) *items*) ((WHISKEY . PLAYER) (WHISKEY . JAR)) (assoc 'whiskey *items*) (WHISKEY . PLAYER) ``` so while #'assoc returns the correct current whiskey location (in the player) we can look into the past and see there's whiskey in the jar. My everything-is-where-it-is abstraction suffers a correctable hiccup here as well. Since the player themselves is not currently a game object, when I had the player #'TAKE something, the item gets taken out of the game world and put in a different list, the player's inventory. The solution to this will be to put the player into the game world (defclass featherless () ()) (defclass biped () ((leg-one) (leg-two))) (defclass player (featherless biped) ((inventory :initform (list)))) and in general have non-location game entities be instances of CLOS classes; and the player and other characters/container items would have inventories, while being inside the game world (my *ROOMS* list). Inventoryable items seem natural to describe in the CLOS way using multiple inheritance: (defclass musical () ()) (defclass fruit () ()) (defclass beans (musical fruit) ()) Which let [] there be multiple objects of the same class that are not EQ if they are not the same object: ``` (setq *dinner-today* (make-instance 'beans)) (setq *mystery-beans* (make-instance 'beans)) (setq *dinner-tomorrow* *mystery-beans*) > (eq *dinner-today* *mystery-beans*) NIL > (eq *dinner-tomorrow* *mystery-beans*) T ``` But Land of Lisp didn't get to CLOS yet. Already I've used common lisp's seedy underbelly's Formatted Output for describing the game world while Land of Lisp is currently using '(VERY DESCRIPTIVE NAME WORDS IN LISTS) to keep data in a processable form (strings will be used as well more later I am promised). I guess I have been using #'SETQ instead of #'DEFPARAMETER. I used #'FIND when I should have used #'MEMBER like Land of Lisp did. When it's clear from context I normally leave off the sharp-sign from a function name, which is allowed, since I like code to look as idiomatic as possible if there is an exceptional clause I try to use it. (defun foo (x) (cons 'foo x)) (mapcar 'foo '(1 2)) ; same as (mapcar #'foo '(1 2)) I am looking forward to seeing some other Land of Lisp wizard game writing phlogs! However loyal or disloyal to the book they be. Trivia: Common lisp names can be case sensitive, or almost anything else but you have to then demarcate them with pipes. (setq |People might think this is a "string".| '|but it isn't.|) > |People might think this is a "string".| |but it isn't.|