diff --git a/ATL/Lugwey/lugwey.atl b/ATL/Lugwey/lugwey.atl index 12f6cd7..7f8c269 100644 --- a/ATL/Lugwey/lugwey.atl +++ b/ATL/Lugwey/lugwey.atl @@ -31,7 +31,9 @@ item "Dagger" weapon "Dagger" money 60 - place "Gate" + place "Chapel" + item "Lantern" +; night-vision load-file "places.atl" load-file "items.atl" diff --git a/ATL/Lugwey/lugwey.atl b/ATL/Lugwey/lugwey.atl index 12f6cd7..7f8c269 100644 --- a/ATL/Lugwey/lugwey.atl +++ b/ATL/Lugwey/lugwey.atl @@ -31,7 +31,9 @@ item "Dagger" weapon "Dagger" money 60 - place "Gate" + place "Chapel" + item "Lantern" +; night-vision load-file "places.atl" load-file "items.atl" diff --git a/ATL/Lugwey/places.atl b/ATL/Lugwey/places.atl index 9b6fefe..58cfc4e 100644 --- a/ATL/Lugwey/places.atl +++ b/ATL/Lugwey/places.atl @@ -44,6 +44,15 @@ neighbour "Monastery grounds" neighbour "Dormitory" neighbour "Cloister" + neighbour "Crypt" + +define-place "Crypt" + description "Your steps echo in the cold, vaulted chamber. Here, underneath + the chapel, is where the monastery's abbots lie buried. Generations + of clerics resting in their stony graves..." + neighbour "Chapel" + dark + define-place "Dormitory" description "" diff --git a/ATL/Lugwey/lugwey.atl b/ATL/Lugwey/lugwey.atl index 12f6cd7..7f8c269 100644 --- a/ATL/Lugwey/lugwey.atl +++ b/ATL/Lugwey/lugwey.atl @@ -31,7 +31,9 @@ item "Dagger" weapon "Dagger" money 60 - place "Gate" + place "Chapel" + item "Lantern" +; night-vision load-file "places.atl" load-file "items.atl" diff --git a/ATL/Lugwey/places.atl b/ATL/Lugwey/places.atl index 9b6fefe..58cfc4e 100644 --- a/ATL/Lugwey/places.atl +++ b/ATL/Lugwey/places.atl @@ -44,6 +44,15 @@ neighbour "Monastery grounds" neighbour "Dormitory" neighbour "Cloister" + neighbour "Crypt" + +define-place "Crypt" + description "Your steps echo in the cold, vaulted chamber. Here, underneath + the chapel, is where the monastery's abbots lie buried. Generations + of clerics resting in their stony graves..." + neighbour "Chapel" + dark + define-place "Dormitory" description "" diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index 7edb8b6..cb5c5f3 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -18,7 +18,8 @@ (player NIL) (item NIL) (monster NIL) - (npc NIL)) + (npc NIL) + (dark NIL)) ;;; WORK IN PROGRESS >>> diff --git a/ATL/Lugwey/lugwey.atl b/ATL/Lugwey/lugwey.atl index 12f6cd7..7f8c269 100644 --- a/ATL/Lugwey/lugwey.atl +++ b/ATL/Lugwey/lugwey.atl @@ -31,7 +31,9 @@ item "Dagger" weapon "Dagger" money 60 - place "Gate" + place "Chapel" + item "Lantern" +; night-vision load-file "places.atl" load-file "items.atl" diff --git a/ATL/Lugwey/places.atl b/ATL/Lugwey/places.atl index 9b6fefe..58cfc4e 100644 --- a/ATL/Lugwey/places.atl +++ b/ATL/Lugwey/places.atl @@ -44,6 +44,15 @@ neighbour "Monastery grounds" neighbour "Dormitory" neighbour "Cloister" + neighbour "Crypt" + +define-place "Crypt" + description "Your steps echo in the cold, vaulted chamber. Here, underneath + the chapel, is where the monastery's abbots lie buried. Generations + of clerics resting in their stony graves..." + neighbour "Chapel" + dark + define-place "Dormitory" description "" diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index 7edb8b6..cb5c5f3 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -18,7 +18,8 @@ (player NIL) (item NIL) (monster NIL) - (npc NIL)) + (npc NIL) + (dark NIL)) ;;; WORK IN PROGRESS >>> diff --git a/lisp/interpreter.lisp b/lisp/interpreter.lisp index 46232f6..76d2dc9 100644 --- a/lisp/interpreter.lisp +++ b/lisp/interpreter.lisp @@ -44,6 +44,7 @@ (loaded-files NIL)) (defun load-file (file-name) "Load and interpret an ATL source file or a Lisp extension file" + ;; XXX Should this be split up into several functions? ;; save/load the current working directory (if (null (pathname-directory file-name)) (setf file-name (make-pathname @@ -92,10 +93,15 @@ ;; TODO allow binary options (options without an argument) ((or (eql (aref line 0) #\Space) (eql (aref line 0) #\Tab)) - (setf line (trim-whitespace line)) - (set-object-attribute current-object (read-from-string line) - (read-from-string - (second (cut-string line (position #\space line)))))) + (let ((options (extract-elements line))) + (case (length options) + (1 (set-object-attribute current-object + (first options) T)) + (2 (set-object-attribute current-object + (first options) (second options))) + ;; FIXME gives problems with lines like this: + ;; " ;commented" + (t (error "~&Too many arguments: '~A'" line))))) (T ;; can't happen (error "~&ERROR: unrecognized syntax: '~A'" line)))))) diff --git a/ATL/Lugwey/lugwey.atl b/ATL/Lugwey/lugwey.atl index 12f6cd7..7f8c269 100644 --- a/ATL/Lugwey/lugwey.atl +++ b/ATL/Lugwey/lugwey.atl @@ -31,7 +31,9 @@ item "Dagger" weapon "Dagger" money 60 - place "Gate" + place "Chapel" + item "Lantern" +; night-vision load-file "places.atl" load-file "items.atl" diff --git a/ATL/Lugwey/places.atl b/ATL/Lugwey/places.atl index 9b6fefe..58cfc4e 100644 --- a/ATL/Lugwey/places.atl +++ b/ATL/Lugwey/places.atl @@ -44,6 +44,15 @@ neighbour "Monastery grounds" neighbour "Dormitory" neighbour "Cloister" + neighbour "Crypt" + +define-place "Crypt" + description "Your steps echo in the cold, vaulted chamber. Here, underneath + the chapel, is where the monastery's abbots lie buried. Generations + of clerics resting in their stony graves..." + neighbour "Chapel" + dark + define-place "Dormitory" description "" diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index 7edb8b6..cb5c5f3 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -18,7 +18,8 @@ (player NIL) (item NIL) (monster NIL) - (npc NIL)) + (npc NIL) + (dark NIL)) ;;; WORK IN PROGRESS >>> diff --git a/lisp/interpreter.lisp b/lisp/interpreter.lisp index 46232f6..76d2dc9 100644 --- a/lisp/interpreter.lisp +++ b/lisp/interpreter.lisp @@ -44,6 +44,7 @@ (loaded-files NIL)) (defun load-file (file-name) "Load and interpret an ATL source file or a Lisp extension file" + ;; XXX Should this be split up into several functions? ;; save/load the current working directory (if (null (pathname-directory file-name)) (setf file-name (make-pathname @@ -92,10 +93,15 @@ ;; TODO allow binary options (options without an argument) ((or (eql (aref line 0) #\Space) (eql (aref line 0) #\Tab)) - (setf line (trim-whitespace line)) - (set-object-attribute current-object (read-from-string line) - (read-from-string - (second (cut-string line (position #\space line)))))) + (let ((options (extract-elements line))) + (case (length options) + (1 (set-object-attribute current-object + (first options) T)) + (2 (set-object-attribute current-object + (first options) (second options))) + ;; FIXME gives problems with lines like this: + ;; " ;commented" + (t (error "~&Too many arguments: '~A'" line))))) (T ;; can't happen (error "~&ERROR: unrecognized syntax: '~A'" line)))))) diff --git a/lisp/player.lisp b/lisp/player.lisp index 61ca6be..ce00de2 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -27,6 +27,7 @@ (level 0) (max-health 50) (health 50) + (night-vision NIL) (game-admin NIL)) ;; How many XP are needed to level up? diff --git a/ATL/Lugwey/lugwey.atl b/ATL/Lugwey/lugwey.atl index 12f6cd7..7f8c269 100644 --- a/ATL/Lugwey/lugwey.atl +++ b/ATL/Lugwey/lugwey.atl @@ -31,7 +31,9 @@ item "Dagger" weapon "Dagger" money 60 - place "Gate" + place "Chapel" + item "Lantern" +; night-vision load-file "places.atl" load-file "items.atl" diff --git a/ATL/Lugwey/places.atl b/ATL/Lugwey/places.atl index 9b6fefe..58cfc4e 100644 --- a/ATL/Lugwey/places.atl +++ b/ATL/Lugwey/places.atl @@ -44,6 +44,15 @@ neighbour "Monastery grounds" neighbour "Dormitory" neighbour "Cloister" + neighbour "Crypt" + +define-place "Crypt" + description "Your steps echo in the cold, vaulted chamber. Here, underneath + the chapel, is where the monastery's abbots lie buried. Generations + of clerics resting in their stony graves..." + neighbour "Chapel" + dark + define-place "Dormitory" description "" diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index 7edb8b6..cb5c5f3 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -18,7 +18,8 @@ (player NIL) (item NIL) (monster NIL) - (npc NIL)) + (npc NIL) + (dark NIL)) ;;; WORK IN PROGRESS >>> diff --git a/lisp/interpreter.lisp b/lisp/interpreter.lisp index 46232f6..76d2dc9 100644 --- a/lisp/interpreter.lisp +++ b/lisp/interpreter.lisp @@ -44,6 +44,7 @@ (loaded-files NIL)) (defun load-file (file-name) "Load and interpret an ATL source file or a Lisp extension file" + ;; XXX Should this be split up into several functions? ;; save/load the current working directory (if (null (pathname-directory file-name)) (setf file-name (make-pathname @@ -92,10 +93,15 @@ ;; TODO allow binary options (options without an argument) ((or (eql (aref line 0) #\Space) (eql (aref line 0) #\Tab)) - (setf line (trim-whitespace line)) - (set-object-attribute current-object (read-from-string line) - (read-from-string - (second (cut-string line (position #\space line)))))) + (let ((options (extract-elements line))) + (case (length options) + (1 (set-object-attribute current-object + (first options) T)) + (2 (set-object-attribute current-object + (first options) (second options))) + ;; FIXME gives problems with lines like this: + ;; " ;commented" + (t (error "~&Too many arguments: '~A'" line))))) (T ;; can't happen (error "~&ERROR: unrecognized syntax: '~A'" line)))))) diff --git a/lisp/player.lisp b/lisp/player.lisp index 61ca6be..ce00de2 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -27,6 +27,7 @@ (level 0) (max-health 50) (health 50) + (night-vision NIL) (game-admin NIL)) ;; How many XP are needed to level up? diff --git a/lisp/ui.lisp b/lisp/ui.lisp index 9e76021..2bdc02b 100644 --- a/lisp/ui.lisp +++ b/lisp/ui.lisp @@ -19,13 +19,13 @@ (let ((player (get-game-object 'player player-name))) (clear-screen) ;; Initialize the player if necessary - (when (null player) + (unless player (setf player (create-player player-name)) (add-player player)) ;; The actual game loop (clear-screen) (let ((place (get-game-object 'place (player-place player)))) - (describe-place place) + (describe-place place (player-night-vision player)) (input-string command) (while (not (or (equalp command "quit") (equalp command "exit"))) (game-command command player) @@ -45,7 +45,7 @@ (items NIL) (weapon "") (character-points NIL)) (format t "~&The name you have chosen is not registered on this game.") - (unless (y-or-n-p "~&Create a new player?") (start-menu)) + (unless (y-or-n-p "~&Create a new player?") (start-menu) (quit)) ;; Chose race and class (format t "~&Please chose a race:") (setf (player-race player) (choose-option (list-world-objects 'race))) @@ -81,18 +81,22 @@ (setf character-points (remove-if #'(lambda (x) (= x val)) character-points))))) -(defun describe-place (p) +(defun describe-place (p &optional (show-dark t)) "Print out a complete description of place p" + ;; XXX This has become slightly ugly with the addition of darkness... (when (stringp p) (setf p (get-game-object 'place p))) (format t "~&~A" (string-upcase (place-name p))) - (format t "~&~%~A" (place-description p)) + (format t "~&~%~A" (if (and (place-dark p) (not show-dark)) + "You do not see a thing in here. It's too dark!" + (place-description p))) (format t "~&~%Neighbouring places: ~A" (string-from-list (place-neighbour p))) - (format t "~&Players present: ~A" (string-from-list (place-player p))) - (format t "~&Items: ~A" (string-from-list (place-item p))) - (format t "~&NPCs: ~A" (string-from-list (place-npc p))) - (format t "~&Monsters: ~A" (string-from-list - (list-place-objects 'monster p)))) + (unless (and (place-dark p) (not show-dark)) + (format t "~&Players present: ~A" (string-from-list (place-player p))) + (format t "~&Items: ~A" (string-from-list (place-item p))) + (format t "~&NPCs: ~A" (string-from-list (place-npc p))) + (format t "~&Monsters: ~A" (string-from-list + (list-place-objects 'monster p))))) (defun game-command (cmd player) "Execute a typed-in game command" @@ -148,7 +152,7 @@ ;; identical with the struct name) Probably not, but best to be aware. (defun place (player) "Describe the player's current location (wrapper function)" - (describe-place (player-place player))) + (describe-place (player-place player) (player-night-vision player))) (defun player (p) "Print a description of this player" @@ -208,7 +212,7 @@ (debugging "~&~A is going to ~A." (player-name player) location) (change-player-location player location) (add-player-experience player 1) - (describe-place location)) + (describe-place location (player-night-vision player))) (defun about (player &optional object-name) "Print a description of this object" diff --git a/ATL/Lugwey/lugwey.atl b/ATL/Lugwey/lugwey.atl index 12f6cd7..7f8c269 100644 --- a/ATL/Lugwey/lugwey.atl +++ b/ATL/Lugwey/lugwey.atl @@ -31,7 +31,9 @@ item "Dagger" weapon "Dagger" money 60 - place "Gate" + place "Chapel" + item "Lantern" +; night-vision load-file "places.atl" load-file "items.atl" diff --git a/ATL/Lugwey/places.atl b/ATL/Lugwey/places.atl index 9b6fefe..58cfc4e 100644 --- a/ATL/Lugwey/places.atl +++ b/ATL/Lugwey/places.atl @@ -44,6 +44,15 @@ neighbour "Monastery grounds" neighbour "Dormitory" neighbour "Cloister" + neighbour "Crypt" + +define-place "Crypt" + description "Your steps echo in the cold, vaulted chamber. Here, underneath + the chapel, is where the monastery's abbots lie buried. Generations + of clerics resting in their stony graves..." + neighbour "Chapel" + dark + define-place "Dormitory" description "" diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index 7edb8b6..cb5c5f3 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -18,7 +18,8 @@ (player NIL) (item NIL) (monster NIL) - (npc NIL)) + (npc NIL) + (dark NIL)) ;;; WORK IN PROGRESS >>> diff --git a/lisp/interpreter.lisp b/lisp/interpreter.lisp index 46232f6..76d2dc9 100644 --- a/lisp/interpreter.lisp +++ b/lisp/interpreter.lisp @@ -44,6 +44,7 @@ (loaded-files NIL)) (defun load-file (file-name) "Load and interpret an ATL source file or a Lisp extension file" + ;; XXX Should this be split up into several functions? ;; save/load the current working directory (if (null (pathname-directory file-name)) (setf file-name (make-pathname @@ -92,10 +93,15 @@ ;; TODO allow binary options (options without an argument) ((or (eql (aref line 0) #\Space) (eql (aref line 0) #\Tab)) - (setf line (trim-whitespace line)) - (set-object-attribute current-object (read-from-string line) - (read-from-string - (second (cut-string line (position #\space line)))))) + (let ((options (extract-elements line))) + (case (length options) + (1 (set-object-attribute current-object + (first options) T)) + (2 (set-object-attribute current-object + (first options) (second options))) + ;; FIXME gives problems with lines like this: + ;; " ;commented" + (t (error "~&Too many arguments: '~A'" line))))) (T ;; can't happen (error "~&ERROR: unrecognized syntax: '~A'" line)))))) diff --git a/lisp/player.lisp b/lisp/player.lisp index 61ca6be..ce00de2 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -27,6 +27,7 @@ (level 0) (max-health 50) (health 50) + (night-vision NIL) (game-admin NIL)) ;; How many XP are needed to level up? diff --git a/lisp/ui.lisp b/lisp/ui.lisp index 9e76021..2bdc02b 100644 --- a/lisp/ui.lisp +++ b/lisp/ui.lisp @@ -19,13 +19,13 @@ (let ((player (get-game-object 'player player-name))) (clear-screen) ;; Initialize the player if necessary - (when (null player) + (unless player (setf player (create-player player-name)) (add-player player)) ;; The actual game loop (clear-screen) (let ((place (get-game-object 'place (player-place player)))) - (describe-place place) + (describe-place place (player-night-vision player)) (input-string command) (while (not (or (equalp command "quit") (equalp command "exit"))) (game-command command player) @@ -45,7 +45,7 @@ (items NIL) (weapon "") (character-points NIL)) (format t "~&The name you have chosen is not registered on this game.") - (unless (y-or-n-p "~&Create a new player?") (start-menu)) + (unless (y-or-n-p "~&Create a new player?") (start-menu) (quit)) ;; Chose race and class (format t "~&Please chose a race:") (setf (player-race player) (choose-option (list-world-objects 'race))) @@ -81,18 +81,22 @@ (setf character-points (remove-if #'(lambda (x) (= x val)) character-points))))) -(defun describe-place (p) +(defun describe-place (p &optional (show-dark t)) "Print out a complete description of place p" + ;; XXX This has become slightly ugly with the addition of darkness... (when (stringp p) (setf p (get-game-object 'place p))) (format t "~&~A" (string-upcase (place-name p))) - (format t "~&~%~A" (place-description p)) + (format t "~&~%~A" (if (and (place-dark p) (not show-dark)) + "You do not see a thing in here. It's too dark!" + (place-description p))) (format t "~&~%Neighbouring places: ~A" (string-from-list (place-neighbour p))) - (format t "~&Players present: ~A" (string-from-list (place-player p))) - (format t "~&Items: ~A" (string-from-list (place-item p))) - (format t "~&NPCs: ~A" (string-from-list (place-npc p))) - (format t "~&Monsters: ~A" (string-from-list - (list-place-objects 'monster p)))) + (unless (and (place-dark p) (not show-dark)) + (format t "~&Players present: ~A" (string-from-list (place-player p))) + (format t "~&Items: ~A" (string-from-list (place-item p))) + (format t "~&NPCs: ~A" (string-from-list (place-npc p))) + (format t "~&Monsters: ~A" (string-from-list + (list-place-objects 'monster p))))) (defun game-command (cmd player) "Execute a typed-in game command" @@ -148,7 +152,7 @@ ;; identical with the struct name) Probably not, but best to be aware. (defun place (player) "Describe the player's current location (wrapper function)" - (describe-place (player-place player))) + (describe-place (player-place player) (player-night-vision player))) (defun player (p) "Print a description of this player" @@ -208,7 +212,7 @@ (debugging "~&~A is going to ~A." (player-name player) location) (change-player-location player location) (add-player-experience player 1) - (describe-place location)) + (describe-place location (player-night-vision player))) (defun about (player &optional object-name) "Print a description of this object" diff --git a/lisp/util.lisp b/lisp/util.lisp index 827b42a..9d86fa4 100644 --- a/lisp/util.lisp +++ b/lisp/util.lisp @@ -135,14 +135,12 @@ (defun cut-string (s i) "Cut string s in two at index i and return the two substrings in a list" - ;; FIXME (cut-string "43" 2) => ("4" "3") ?! - (do* ((c 0 (1+ c)) (letter (aref s c) (aref s c)) - (letter-list-1 NIL) (letter-list-2 NIL)) - ((= c (1- (length s))) - (list (list-to-string (append letter-list-1)) - (list-to-string (append letter-list-2 (list letter))))) - (if (< c i) (setf letter-list-1 (append letter-list-1 (list letter))) - (setf letter-list-2 (append letter-list-2 (list letter)))))) + (if (or (minusp i) (> i (length s))) s + (let ((s1 (make-string i)) (s2 (make-string (- (length s) i)))) + (dotimes (c (length s) (list s1 s2)) + (if (> i c) + (setf (aref s1 c) (aref s c)) + (setf (aref s2 (- c i)) (aref s c))))))) (defun list-to-string (char-list) "Convert a character list to a string" @@ -160,6 +158,13 @@ ((or (symbolp x) (characterp x)) (string x)) (t (format NIL "~S" x)))) +(defun extract-elements (str) + "Extract all Lisp elements (strings, symbols, numbers, etc.) from str" + (multiple-value-bind (next-element i) (read-from-string str nil) + (if (null next-element) NIL + (cons next-element + (extract-elements (second (cut-string str i))))))) + (defun count-instances (search-term search-sequence &key (test #'eql)) "Count the number of instances of search-term in search-sequence" (let ((count 0)) @@ -178,6 +183,13 @@ (if (= next-elt (1- (length vector))) NIL (cons (aref vector next-elt) (to-list vector (1+ next-elt))))) +(defun cut-list (l i) + "Cut list l in two at index i and return the two sublists in a list" + (if (or (< i 1) (> i (length l))) l + (do* ((lst2 l (cdr lst2)) + (lst1 (list (car lst2)) (append lst1 (list (car lst2))))) + ((= i (length lst1)) (list lst1 (cdr lst2)))))) + (defun random-elt (seq) "Return a random element of this sequence" (elt seq (random (length seq))))