Created
August 13, 2009 15:52
-
-
Save KirinDave/167252 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;; 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