Skip to content

Instantly share code, notes, and snippets.

@KirinDave
Created August 13, 2009 15:52
Show Gist options
  • Select an option

  • Save KirinDave/167252 to your computer and use it in GitHub Desktop.

Select an option

Save KirinDave/167252 to your computer and use it in GitHub Desktop.
;; We define a "struct", which is like a C struct, for the rooms. Note that there
;; Are default values which can be used if we omit one from construction.
(defstruct my-room
(desc "An empty room.")
;; The exits will be a list of lists, what lispniks call an "assoc-list"
;; like so: ( (north room1) (south room2) )
;; Think of it as a kind of simple tree.
(exits ()))
;; This function does the work of "displaying" a room.
;; It shows a room, its exits,
;; and then waits for the user to type in a valid exit.
;; The Lisp reader is what we use,
;; which means we can do some funny things.
(defun run-room (loc)
;; Firstly, we fetch the fields "name" and "exits" from the room structure.
(let ( (desc (my-room-desc loc))
(exits (my-room-exits loc)) )
;; Format is Lisp's printf, with all that entails. This prints out the room
;; description and then prints out a line "Exits:"
(format t "~%~a~%~%Exits:~%" desc)
;; Dolist does just what it sounds like. It does the statement for each
;; member of the list in "exits". In this case, it displays the name of each
;; exit on its own line
(dolist (x exits) (format t "~a~%" (first x)))
;; Then we print a prompt
(format t "~%> ")
;; We use LOOP here, instead of the more obtuse do macro. The general idea
;; is to keep reading from input, letting lisp do the parsing.
;; We check if the input is a valid exit (if it exists in the assoc list)
;; and if so we return the SYMBOL that is in the next result. So we'd return
;; the NAME "forestroom" instead of the actual instance forestroom. This is
;; only to make things more convenient.
(loop for dir = (read)
for arc = (assoc dir exits)
when arc
do (return (second arc))
else do (format t "You cannot go ~a~%> " dir)))))
;; This function actually starts the maze. You just say (run-maze room1) or whatever
;; It is another loop. All it does is keep looping over rooms, making sure that if
;; the symbol "DONE" is ever returned, to terminate the loop. This means the maze can
;; actually end. :)
;; The "symbol-value" means "get the value at the symbol", which is pretty useful here
;; since it means that rooms don't depend on each other, only on symbols which lisp provides.
(defun run-maze (start)
(loop for next = (run-room start)
then (run-room (symbol-value next))
while (not (eq next 'done))))
;; This is a macro, which means fancy syntactic sugar. All it does is
;; make it so that our room definitions can look pretty, and can safely
;; be ignored.
(defmacro def-room (name desc &rest exit-pairs)
`(defvar ,name (make-my-room :desc ,desc
:exits ',exit-pairs)))
;; The example dungeon from the C page, with some slight changes.
;; Our macro makes our room definitions very pretty.
;; Note that we refer to rooms by name
;; without caring if they are made yet or not.
;; This is because we refer to them symbolically,
;; and run-maze is wise to this
;; and understands to look up the value at the symbol.
;; That kind of coding is one of the real benefits of lisp's approach.
(def-room footpath
"You are on a footpath. You can see a forest to the north."
(north forest) (south stream-room))
(def-room forest
"You are in a forest. You can hear water running to the south."
(north clearing) (south footpath)
(east trees))
;; A bonus room ;)
(def-room trees
"You are in a forest, but you can't see it because of the trees."
(west forest) (east footpath))
(def-room clearing
"The forest thins to a clearing. There is a strange radiance north."
(north circle) (south forest))
(def-room circle
"There is a circle of little pixies here. They glow. Like fire."
(south forest) (circle endgame))
(def-room stream-room
"You are next to a stream. You can see a bridge to the west."
(west bridge) (north footpath))
(def-room bridge
"A tiny bridge leading to the southern fort. The path goes east."
(east stream-room) (south fort))
(def-room fort
"You have reached your little fort. It is empty save for your bed."
(bed endgame) (north bridge))
(def-room endgame
"There. You've finished the game. Gratz!"
(done done))
#|
;; Example call:
(run-maze footpath)
|#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment