diff --git a/ATL/Pooh/pooh-extensions.lisp b/ATL/Pooh/pooh-extensions.lisp index 6ecfbaa..a780171 100644 --- a/ATL/Pooh/pooh-extensions.lisp +++ b/ATL/Pooh/pooh-extensions.lisp @@ -109,7 +109,7 @@ (if (member 'down (extract-elements arg)) (climb-down player) (format t "~&You are already sitting up the tree.")) - (return-from climb)) + (return-from climb-tree)) (format t "~&You start climbing up the tree.") (sleep 3) ;; The player has a 60% chance of success. diff --git a/ATL/Pooh/pooh-extensions.lisp b/ATL/Pooh/pooh-extensions.lisp index 6ecfbaa..a780171 100644 --- a/ATL/Pooh/pooh-extensions.lisp +++ b/ATL/Pooh/pooh-extensions.lisp @@ -109,7 +109,7 @@ (if (member 'down (extract-elements arg)) (climb-down player) (format t "~&You are already sitting up the tree.")) - (return-from climb)) + (return-from climb-tree)) (format t "~&You start climbing up the tree.") (sleep 3) ;; The player has a 60% chance of success. diff --git a/ATL/Pooh/pooh.atl b/ATL/Pooh/pooh.atl index 79db160..7a4009f 100644 --- a/ATL/Pooh/pooh.atl +++ b/ATL/Pooh/pooh.atl @@ -17,13 +17,13 @@ define-player "Winnie the Pooh" description "A small but lovable bear of Very Little Brain." place "Pooh's home" - ;place "Sandy pit" ;Development max-health 20 health 20 strength 1 dexterity 4 constitution 4 -;define-player "Christopher Robin" -; description "Just debugging..." -; place "Christopher Robin's house" \ No newline at end of file +define-player "Christopher Robin" + description "Christopher Robin is my game dev character." + place "Sandy pit" ;Development + ;place "Christopher Robin's house" \ No newline at end of file diff --git a/ATL/Pooh/pooh-extensions.lisp b/ATL/Pooh/pooh-extensions.lisp index 6ecfbaa..a780171 100644 --- a/ATL/Pooh/pooh-extensions.lisp +++ b/ATL/Pooh/pooh-extensions.lisp @@ -109,7 +109,7 @@ (if (member 'down (extract-elements arg)) (climb-down player) (format t "~&You are already sitting up the tree.")) - (return-from climb)) + (return-from climb-tree)) (format t "~&You start climbing up the tree.") (sleep 3) ;; The player has a 60% chance of success. diff --git a/ATL/Pooh/pooh.atl b/ATL/Pooh/pooh.atl index 79db160..7a4009f 100644 --- a/ATL/Pooh/pooh.atl +++ b/ATL/Pooh/pooh.atl @@ -17,13 +17,13 @@ define-player "Winnie the Pooh" description "A small but lovable bear of Very Little Brain." place "Pooh's home" - ;place "Sandy pit" ;Development max-health 20 health 20 strength 1 dexterity 4 constitution 4 -;define-player "Christopher Robin" -; description "Just debugging..." -; place "Christopher Robin's house" \ No newline at end of file +define-player "Christopher Robin" + description "Christopher Robin is my game dev character." + place "Sandy pit" ;Development + ;place "Christopher Robin's house" \ No newline at end of file diff --git a/doc/COMMANDS b/doc/COMMANDS new file mode 100644 index 0000000..2ab862a --- /dev/null +++ b/doc/COMMANDS @@ -0,0 +1,25 @@ +COMMANDS: +help - Show this list of game commands +manual - Show a detailed game manual +quit/exit - Exit the game +clear - Clear the screen +look [here] - Describe the current location +look - Show a description of this entity +look me - Describe your character +inventory - Same as 'look me' +goto - Go to a neighbouring location +take - Pick up an item lying around +drop - Drop the item +talk [to] - Talk to an NPC +seek - Search for hidden items +equip - Equip this item as your weapon +attack - Fight a monster +save [] - Save the game to file + +Arguments in square brackets are optional, +arguments in angular brackets denote place fillers. + +If you abbreviate commands or arguments, Atlantis will +try to find a suitable match. + +Some places and items may provide additional commands. diff --git a/ATL/Pooh/pooh-extensions.lisp b/ATL/Pooh/pooh-extensions.lisp index 6ecfbaa..a780171 100644 --- a/ATL/Pooh/pooh-extensions.lisp +++ b/ATL/Pooh/pooh-extensions.lisp @@ -109,7 +109,7 @@ (if (member 'down (extract-elements arg)) (climb-down player) (format t "~&You are already sitting up the tree.")) - (return-from climb)) + (return-from climb-tree)) (format t "~&You start climbing up the tree.") (sleep 3) ;; The player has a 60% chance of success. diff --git a/ATL/Pooh/pooh.atl b/ATL/Pooh/pooh.atl index 79db160..7a4009f 100644 --- a/ATL/Pooh/pooh.atl +++ b/ATL/Pooh/pooh.atl @@ -17,13 +17,13 @@ define-player "Winnie the Pooh" description "A small but lovable bear of Very Little Brain." place "Pooh's home" - ;place "Sandy pit" ;Development max-health 20 health 20 strength 1 dexterity 4 constitution 4 -;define-player "Christopher Robin" -; description "Just debugging..." -; place "Christopher Robin's house" \ No newline at end of file +define-player "Christopher Robin" + description "Christopher Robin is my game dev character." + place "Sandy pit" ;Development + ;place "Christopher Robin's house" \ No newline at end of file diff --git a/doc/COMMANDS b/doc/COMMANDS new file mode 100644 index 0000000..2ab862a --- /dev/null +++ b/doc/COMMANDS @@ -0,0 +1,25 @@ +COMMANDS: +help - Show this list of game commands +manual - Show a detailed game manual +quit/exit - Exit the game +clear - Clear the screen +look [here] - Describe the current location +look - Show a description of this entity +look me - Describe your character +inventory - Same as 'look me' +goto - Go to a neighbouring location +take - Pick up an item lying around +drop - Drop the item +talk [to] - Talk to an NPC +seek - Search for hidden items +equip - Equip this item as your weapon +attack - Fight a monster +save [] - Save the game to file + +Arguments in square brackets are optional, +arguments in angular brackets denote place fillers. + +If you abbreviate commands or arguments, Atlantis will +try to find a suitable match. + +Some places and items may provide additional commands. diff --git a/doc/TODO b/doc/TODO index 14b6174..ef5aba7 100644 --- a/doc/TODO +++ b/doc/TODO @@ -2,6 +2,8 @@ LISP * prevent illegal input characters from causing a crash +* test all commands again after fuzzy-matching was added +* split ui.lisp into two modules (one for interaction functions) ATL * fill in missing place descriptions diff --git a/ATL/Pooh/pooh-extensions.lisp b/ATL/Pooh/pooh-extensions.lisp index 6ecfbaa..a780171 100644 --- a/ATL/Pooh/pooh-extensions.lisp +++ b/ATL/Pooh/pooh-extensions.lisp @@ -109,7 +109,7 @@ (if (member 'down (extract-elements arg)) (climb-down player) (format t "~&You are already sitting up the tree.")) - (return-from climb)) + (return-from climb-tree)) (format t "~&You start climbing up the tree.") (sleep 3) ;; The player has a 60% chance of success. diff --git a/ATL/Pooh/pooh.atl b/ATL/Pooh/pooh.atl index 79db160..7a4009f 100644 --- a/ATL/Pooh/pooh.atl +++ b/ATL/Pooh/pooh.atl @@ -17,13 +17,13 @@ define-player "Winnie the Pooh" description "A small but lovable bear of Very Little Brain." place "Pooh's home" - ;place "Sandy pit" ;Development max-health 20 health 20 strength 1 dexterity 4 constitution 4 -;define-player "Christopher Robin" -; description "Just debugging..." -; place "Christopher Robin's house" \ No newline at end of file +define-player "Christopher Robin" + description "Christopher Robin is my game dev character." + place "Sandy pit" ;Development + ;place "Christopher Robin's house" \ No newline at end of file diff --git a/doc/COMMANDS b/doc/COMMANDS new file mode 100644 index 0000000..2ab862a --- /dev/null +++ b/doc/COMMANDS @@ -0,0 +1,25 @@ +COMMANDS: +help - Show this list of game commands +manual - Show a detailed game manual +quit/exit - Exit the game +clear - Clear the screen +look [here] - Describe the current location +look - Show a description of this entity +look me - Describe your character +inventory - Same as 'look me' +goto - Go to a neighbouring location +take - Pick up an item lying around +drop - Drop the item +talk [to] - Talk to an NPC +seek - Search for hidden items +equip - Equip this item as your weapon +attack - Fight a monster +save [] - Save the game to file + +Arguments in square brackets are optional, +arguments in angular brackets denote place fillers. + +If you abbreviate commands or arguments, Atlantis will +try to find a suitable match. + +Some places and items may provide additional commands. diff --git a/doc/TODO b/doc/TODO index 14b6174..ef5aba7 100644 --- a/doc/TODO +++ b/doc/TODO @@ -2,6 +2,8 @@ LISP * prevent illegal input characters from causing a crash +* test all commands again after fuzzy-matching was added +* split ui.lisp into two modules (one for interaction functions) ATL * fill in missing place descriptions diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index f54c418..33d3de7 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -59,7 +59,7 @@ (pickup-hook "") (drop-hook "") (command NIL) - (ability NIL)) ;XXX Remove abilities again? + (ability NIL)) ;TODO Remove abilities again (defstruct weapon (name "") diff --git a/ATL/Pooh/pooh-extensions.lisp b/ATL/Pooh/pooh-extensions.lisp index 6ecfbaa..a780171 100644 --- a/ATL/Pooh/pooh-extensions.lisp +++ b/ATL/Pooh/pooh-extensions.lisp @@ -109,7 +109,7 @@ (if (member 'down (extract-elements arg)) (climb-down player) (format t "~&You are already sitting up the tree.")) - (return-from climb)) + (return-from climb-tree)) (format t "~&You start climbing up the tree.") (sleep 3) ;; The player has a 60% chance of success. diff --git a/ATL/Pooh/pooh.atl b/ATL/Pooh/pooh.atl index 79db160..7a4009f 100644 --- a/ATL/Pooh/pooh.atl +++ b/ATL/Pooh/pooh.atl @@ -17,13 +17,13 @@ define-player "Winnie the Pooh" description "A small but lovable bear of Very Little Brain." place "Pooh's home" - ;place "Sandy pit" ;Development max-health 20 health 20 strength 1 dexterity 4 constitution 4 -;define-player "Christopher Robin" -; description "Just debugging..." -; place "Christopher Robin's house" \ No newline at end of file +define-player "Christopher Robin" + description "Christopher Robin is my game dev character." + place "Sandy pit" ;Development + ;place "Christopher Robin's house" \ No newline at end of file diff --git a/doc/COMMANDS b/doc/COMMANDS new file mode 100644 index 0000000..2ab862a --- /dev/null +++ b/doc/COMMANDS @@ -0,0 +1,25 @@ +COMMANDS: +help - Show this list of game commands +manual - Show a detailed game manual +quit/exit - Exit the game +clear - Clear the screen +look [here] - Describe the current location +look - Show a description of this entity +look me - Describe your character +inventory - Same as 'look me' +goto - Go to a neighbouring location +take - Pick up an item lying around +drop - Drop the item +talk [to] - Talk to an NPC +seek - Search for hidden items +equip - Equip this item as your weapon +attack - Fight a monster +save [] - Save the game to file + +Arguments in square brackets are optional, +arguments in angular brackets denote place fillers. + +If you abbreviate commands or arguments, Atlantis will +try to find a suitable match. + +Some places and items may provide additional commands. diff --git a/doc/TODO b/doc/TODO index 14b6174..ef5aba7 100644 --- a/doc/TODO +++ b/doc/TODO @@ -2,6 +2,8 @@ LISP * prevent illegal input characters from causing a crash +* test all commands again after fuzzy-matching was added +* split ui.lisp into two modules (one for interaction functions) ATL * fill in missing place descriptions diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index f54c418..33d3de7 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -59,7 +59,7 @@ (pickup-hook "") (drop-hook "") (command NIL) - (ability NIL)) ;XXX Remove abilities again? + (ability NIL)) ;TODO Remove abilities again (defstruct weapon (name "") diff --git a/lisp/player.lisp b/lisp/player.lisp index c56284f..f693914 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -18,6 +18,7 @@ (constitution 0) (intelligence 0) (money 0) + ;TODO Remove abilities again (ability NIL) (item NIL) (weapon "") diff --git a/ATL/Pooh/pooh-extensions.lisp b/ATL/Pooh/pooh-extensions.lisp index 6ecfbaa..a780171 100644 --- a/ATL/Pooh/pooh-extensions.lisp +++ b/ATL/Pooh/pooh-extensions.lisp @@ -109,7 +109,7 @@ (if (member 'down (extract-elements arg)) (climb-down player) (format t "~&You are already sitting up the tree.")) - (return-from climb)) + (return-from climb-tree)) (format t "~&You start climbing up the tree.") (sleep 3) ;; The player has a 60% chance of success. diff --git a/ATL/Pooh/pooh.atl b/ATL/Pooh/pooh.atl index 79db160..7a4009f 100644 --- a/ATL/Pooh/pooh.atl +++ b/ATL/Pooh/pooh.atl @@ -17,13 +17,13 @@ define-player "Winnie the Pooh" description "A small but lovable bear of Very Little Brain." place "Pooh's home" - ;place "Sandy pit" ;Development max-health 20 health 20 strength 1 dexterity 4 constitution 4 -;define-player "Christopher Robin" -; description "Just debugging..." -; place "Christopher Robin's house" \ No newline at end of file +define-player "Christopher Robin" + description "Christopher Robin is my game dev character." + place "Sandy pit" ;Development + ;place "Christopher Robin's house" \ No newline at end of file diff --git a/doc/COMMANDS b/doc/COMMANDS new file mode 100644 index 0000000..2ab862a --- /dev/null +++ b/doc/COMMANDS @@ -0,0 +1,25 @@ +COMMANDS: +help - Show this list of game commands +manual - Show a detailed game manual +quit/exit - Exit the game +clear - Clear the screen +look [here] - Describe the current location +look - Show a description of this entity +look me - Describe your character +inventory - Same as 'look me' +goto - Go to a neighbouring location +take - Pick up an item lying around +drop - Drop the item +talk [to] - Talk to an NPC +seek - Search for hidden items +equip - Equip this item as your weapon +attack - Fight a monster +save [] - Save the game to file + +Arguments in square brackets are optional, +arguments in angular brackets denote place fillers. + +If you abbreviate commands or arguments, Atlantis will +try to find a suitable match. + +Some places and items may provide additional commands. diff --git a/doc/TODO b/doc/TODO index 14b6174..ef5aba7 100644 --- a/doc/TODO +++ b/doc/TODO @@ -2,6 +2,8 @@ LISP * prevent illegal input characters from causing a crash +* test all commands again after fuzzy-matching was added +* split ui.lisp into two modules (one for interaction functions) ATL * fill in missing place descriptions diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index f54c418..33d3de7 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -59,7 +59,7 @@ (pickup-hook "") (drop-hook "") (command NIL) - (ability NIL)) ;XXX Remove abilities again? + (ability NIL)) ;TODO Remove abilities again (defstruct weapon (name "") diff --git a/lisp/player.lisp b/lisp/player.lisp index c56284f..f693914 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -18,6 +18,7 @@ (constitution 0) (intelligence 0) (money 0) + ;TODO Remove abilities again (ability NIL) (item NIL) (weapon "") diff --git a/lisp/ui.lisp b/lisp/ui.lisp index 1673593..e334485 100644 --- a/lisp/ui.lisp +++ b/lisp/ui.lisp @@ -14,6 +14,8 @@ ;; (This module should be purely UI) ;; Yeah, probably not going to happen ;-) +;; TODO Split module in two + ;; XXX Change to 5 once the (string-from-list) bug is fixed (setf *max-line-items* 10) @@ -101,11 +103,13 @@ ;; Search for place commands (let ((place-cmd (fuzzy-match (to-string command) (place-command (get-game-object 'place - (player-place player)))))) + (player-place player))) + :strict T))) (when place-cmd (setf cmd-fn (read-from-string place-cmd)))) ;; Search for item commands (highest priority) (dolist (i (objectify-name-list 'item (player-item player))) - (let ((item-cmd (fuzzy-match (to-string command) (item-command i)))) + (let ((item-cmd (fuzzy-match (to-string command) + (item-command i) :strict T))) (when item-cmd (setf cmd-fn (read-from-string item-cmd)) (return)))) ;; If found, execute the command (if cmd-fn @@ -120,46 +124,31 @@ ;; A list of all in-game commands. Each new command must be registered here. (defvar *commands* - '(help look goto take + '(help look goto take inventory drop talk equip attack - seek save clear)) + seek save clear manual)) ;;; Command functions have to take two arguments (a player instance and ;;; an optional(!) argument to the function). (defun help (player &optional arg) "Print out a list of in-game commands" - (setf help-text " -COMMANDS: -help - Show this list of game commands -quit/exit - Exit the game -clear - Clear the screen -look [here] - Describe the current location -look me - Describe your character -look - Show a description of this entity -goto - Go to a neighbouring location -take - Pick up an item lying around -drop - Drop the item -talk [to] - Talk to an NPC -seek - Search for hidden items -equip - Equip this item as your weapon -attack - Fight a monster -save [] - Save the game to file + (print-text-file "../doc/COMMANDS")) -Arguments in square brackets are optional, -arguments in angular brackets denote place fillers. - -If you abbreviate commands or arguments, Atlantis will -try to find a suitable match. - -Some places and items may provide additional commands.") - (format t "~A" help-text)) +(defun manual (player &optional arg) + "Show the game manual in a pager" + (pager "../doc/PLAYING" T) + (clear player)) (defun clear (player &optional arg) "Clear the screen (wrapper function)" (clear-screen) (describe-place (player-place player))) +(defun inventory (player &optional arg) + "A wrapper for 'look me'" + (look player "me")) + (let ((last-save NIL)) (defun save (player &optional game-file) "Save a game to file (wrapper method around save-world)" @@ -251,10 +240,11 @@ (defun talk (player &optional npc-name) "Talk to the desired NPC" + ;; TODO Insert fuzzy-match (unless npc-name (format t "~&Please specify an NPC to talk to!") (return-from talk)) - ;; Allow for a bit of syntactic sugar (note: interface inconsistency?) + ;; Allow for a bit of syntactic sugar (let ((split-name (cut-string npc-name 3))) (when (equalp (first split-name) "to ") (setf npc-name (second split-name)))) @@ -279,35 +269,43 @@ (y-or-n-p "Trade with ~A?" npc-name)) (trade player npc)) ;; Handle quests - (let ((quest (get-game-object 'quest (npc-quest npc)))) - (when quest - (if (dolist (i (quest-proof-item quest)) - (unless (member i (player-item player) :test #'equalp) - (return T))) - (when (y-or-n-p "~%~A has a quest. Accept it?" npc-name) - (format t "~&~A: ~A" (string-upcase npc-name) - (quest-say-before quest))) - (when (y-or-n-p "~%Give to ~A: ~A?" npc-name - (string-from-list (quest-proof-item quest) :sep ", " - :line-length *max-line-items*)) - (dolist (j (quest-proof-item quest)) - (remove-object-attribute player 'item j)) - (dolist (k (quest-reward-item quest)) - (set-object-attribute player 'item k)) - (add-player-experience player (quest-experience quest)) - (add-player-money player (quest-money quest)) - (format t "~&~A: ~A" (string-upcase npc-name) - (quest-say-after quest)) - (format t "~&~%Quest complete. You gain:") - (format t "~&Money: ~A Experience: ~A~&Items: ~A" - (quest-money quest) (quest-experience quest) - (string-from-list (quest-reward-item quest) - :line-length *max-line-items*)) - (unless (quest-infinite quest) - (remove-object-attribute npc 'quest npc)))))))) + (unless (zerop (length (npc-quest npc))) + (quest player npc)))) + +(defun quest (player npc) + "Handle NPC quests" + (let ((quest (get-game-object 'quest (npc-quest npc))) + (npc-name (npc-name npc))) + (unless quest (format t "~&This NPC doesn't have a quest!") + (return-from quest)) + (if (dolist (i (quest-proof-item quest)) + (unless (member i (player-item player) :test #'equalp) + (return T))) + (when (y-or-n-p "~%~A has a quest. Accept it?" npc-name) + (format t "~&~A: ~A" (string-upcase npc-name) + (quest-say-before quest))) + (when (y-or-n-p "~%Give to ~A: ~A?" npc-name + (string-from-list (quest-proof-item quest) :sep ", " + :line-length *max-line-items*)) + (dolist (j (quest-proof-item quest)) + (remove-object-attribute player 'item j)) + (dolist (k (quest-reward-item quest)) + (set-object-attribute player 'item k)) + (add-player-experience player (quest-experience quest)) + (add-player-money player (quest-money quest)) + (format t "~&~A: ~A" (string-upcase npc-name) + (quest-say-after quest)) + (format t "~&~%Quest complete. You gain:") + (format t "~&Money: ~A Experience: ~A~&Items: ~A" + (quest-money quest) (quest-experience quest) + (string-from-list (quest-reward-item quest) + :line-length *max-line-items*)) + (unless (quest-infinite quest) + (remove-object-attribute npc 'quest npc)))))) (defun trade (player npc) "The player trades with this NPC" + ;; XXX This is no longer a game command - remove the leading check? (when (and (stringp npc) (member npc (place-npc (get-game-object 'place (player-place player))) @@ -364,6 +362,7 @@ (unless item-name (format t "~&Please specify an item to pick up!") (return-from take)) + ;; TODO Insert fuzzy-match (let ((place (get-game-object 'place (player-place player))) (item-name (string-capitalize item-name)) (item (get-game-object 'item item-name))) @@ -390,6 +389,7 @@ (format t "~&Please specify an item to drop!") (return-from drop)) (setf item (string-capitalize item)) + ;; TODO Insert fuzzy-match (if (member item (player-item player) :test #'equalp) (progn (remove-object-attribute player 'item item) @@ -408,6 +408,7 @@ (defun equip (player &optional new-weapon) "The player sets another item to be his weapon" ;;XXX Replace this with 'hold'? (Also possible for non-weapons.) + ;; TODO Insert fuzzy-match (unless new-weapon (format t "~&Please specify a weapon to be equipped!") (return-from equip)) @@ -429,6 +430,7 @@ (unless opponent (format t "~&Please specify an opponent!") (return-from attack)) + ;; TODO Insert fuzzy-match (unless (member opponent (list-place-objects 'monster (get-game-object 'place (player-place player))) diff --git a/ATL/Pooh/pooh-extensions.lisp b/ATL/Pooh/pooh-extensions.lisp index 6ecfbaa..a780171 100644 --- a/ATL/Pooh/pooh-extensions.lisp +++ b/ATL/Pooh/pooh-extensions.lisp @@ -109,7 +109,7 @@ (if (member 'down (extract-elements arg)) (climb-down player) (format t "~&You are already sitting up the tree.")) - (return-from climb)) + (return-from climb-tree)) (format t "~&You start climbing up the tree.") (sleep 3) ;; The player has a 60% chance of success. diff --git a/ATL/Pooh/pooh.atl b/ATL/Pooh/pooh.atl index 79db160..7a4009f 100644 --- a/ATL/Pooh/pooh.atl +++ b/ATL/Pooh/pooh.atl @@ -17,13 +17,13 @@ define-player "Winnie the Pooh" description "A small but lovable bear of Very Little Brain." place "Pooh's home" - ;place "Sandy pit" ;Development max-health 20 health 20 strength 1 dexterity 4 constitution 4 -;define-player "Christopher Robin" -; description "Just debugging..." -; place "Christopher Robin's house" \ No newline at end of file +define-player "Christopher Robin" + description "Christopher Robin is my game dev character." + place "Sandy pit" ;Development + ;place "Christopher Robin's house" \ No newline at end of file diff --git a/doc/COMMANDS b/doc/COMMANDS new file mode 100644 index 0000000..2ab862a --- /dev/null +++ b/doc/COMMANDS @@ -0,0 +1,25 @@ +COMMANDS: +help - Show this list of game commands +manual - Show a detailed game manual +quit/exit - Exit the game +clear - Clear the screen +look [here] - Describe the current location +look - Show a description of this entity +look me - Describe your character +inventory - Same as 'look me' +goto - Go to a neighbouring location +take - Pick up an item lying around +drop - Drop the item +talk [to] - Talk to an NPC +seek - Search for hidden items +equip - Equip this item as your weapon +attack - Fight a monster +save [] - Save the game to file + +Arguments in square brackets are optional, +arguments in angular brackets denote place fillers. + +If you abbreviate commands or arguments, Atlantis will +try to find a suitable match. + +Some places and items may provide additional commands. diff --git a/doc/TODO b/doc/TODO index 14b6174..ef5aba7 100644 --- a/doc/TODO +++ b/doc/TODO @@ -2,6 +2,8 @@ LISP * prevent illegal input characters from causing a crash +* test all commands again after fuzzy-matching was added +* split ui.lisp into two modules (one for interaction functions) ATL * fill in missing place descriptions diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp index f54c418..33d3de7 100644 --- a/lisp/game-objects.lisp +++ b/lisp/game-objects.lisp @@ -59,7 +59,7 @@ (pickup-hook "") (drop-hook "") (command NIL) - (ability NIL)) ;XXX Remove abilities again? + (ability NIL)) ;TODO Remove abilities again (defstruct weapon (name "") diff --git a/lisp/player.lisp b/lisp/player.lisp index c56284f..f693914 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -18,6 +18,7 @@ (constitution 0) (intelligence 0) (money 0) + ;TODO Remove abilities again (ability NIL) (item NIL) (weapon "") diff --git a/lisp/ui.lisp b/lisp/ui.lisp index 1673593..e334485 100644 --- a/lisp/ui.lisp +++ b/lisp/ui.lisp @@ -14,6 +14,8 @@ ;; (This module should be purely UI) ;; Yeah, probably not going to happen ;-) +;; TODO Split module in two + ;; XXX Change to 5 once the (string-from-list) bug is fixed (setf *max-line-items* 10) @@ -101,11 +103,13 @@ ;; Search for place commands (let ((place-cmd (fuzzy-match (to-string command) (place-command (get-game-object 'place - (player-place player)))))) + (player-place player))) + :strict T))) (when place-cmd (setf cmd-fn (read-from-string place-cmd)))) ;; Search for item commands (highest priority) (dolist (i (objectify-name-list 'item (player-item player))) - (let ((item-cmd (fuzzy-match (to-string command) (item-command i)))) + (let ((item-cmd (fuzzy-match (to-string command) + (item-command i) :strict T))) (when item-cmd (setf cmd-fn (read-from-string item-cmd)) (return)))) ;; If found, execute the command (if cmd-fn @@ -120,46 +124,31 @@ ;; A list of all in-game commands. Each new command must be registered here. (defvar *commands* - '(help look goto take + '(help look goto take inventory drop talk equip attack - seek save clear)) + seek save clear manual)) ;;; Command functions have to take two arguments (a player instance and ;;; an optional(!) argument to the function). (defun help (player &optional arg) "Print out a list of in-game commands" - (setf help-text " -COMMANDS: -help - Show this list of game commands -quit/exit - Exit the game -clear - Clear the screen -look [here] - Describe the current location -look me - Describe your character -look - Show a description of this entity -goto - Go to a neighbouring location -take - Pick up an item lying around -drop - Drop the item -talk [to] - Talk to an NPC -seek - Search for hidden items -equip - Equip this item as your weapon -attack - Fight a monster -save [] - Save the game to file + (print-text-file "../doc/COMMANDS")) -Arguments in square brackets are optional, -arguments in angular brackets denote place fillers. - -If you abbreviate commands or arguments, Atlantis will -try to find a suitable match. - -Some places and items may provide additional commands.") - (format t "~A" help-text)) +(defun manual (player &optional arg) + "Show the game manual in a pager" + (pager "../doc/PLAYING" T) + (clear player)) (defun clear (player &optional arg) "Clear the screen (wrapper function)" (clear-screen) (describe-place (player-place player))) +(defun inventory (player &optional arg) + "A wrapper for 'look me'" + (look player "me")) + (let ((last-save NIL)) (defun save (player &optional game-file) "Save a game to file (wrapper method around save-world)" @@ -251,10 +240,11 @@ (defun talk (player &optional npc-name) "Talk to the desired NPC" + ;; TODO Insert fuzzy-match (unless npc-name (format t "~&Please specify an NPC to talk to!") (return-from talk)) - ;; Allow for a bit of syntactic sugar (note: interface inconsistency?) + ;; Allow for a bit of syntactic sugar (let ((split-name (cut-string npc-name 3))) (when (equalp (first split-name) "to ") (setf npc-name (second split-name)))) @@ -279,35 +269,43 @@ (y-or-n-p "Trade with ~A?" npc-name)) (trade player npc)) ;; Handle quests - (let ((quest (get-game-object 'quest (npc-quest npc)))) - (when quest - (if (dolist (i (quest-proof-item quest)) - (unless (member i (player-item player) :test #'equalp) - (return T))) - (when (y-or-n-p "~%~A has a quest. Accept it?" npc-name) - (format t "~&~A: ~A" (string-upcase npc-name) - (quest-say-before quest))) - (when (y-or-n-p "~%Give to ~A: ~A?" npc-name - (string-from-list (quest-proof-item quest) :sep ", " - :line-length *max-line-items*)) - (dolist (j (quest-proof-item quest)) - (remove-object-attribute player 'item j)) - (dolist (k (quest-reward-item quest)) - (set-object-attribute player 'item k)) - (add-player-experience player (quest-experience quest)) - (add-player-money player (quest-money quest)) - (format t "~&~A: ~A" (string-upcase npc-name) - (quest-say-after quest)) - (format t "~&~%Quest complete. You gain:") - (format t "~&Money: ~A Experience: ~A~&Items: ~A" - (quest-money quest) (quest-experience quest) - (string-from-list (quest-reward-item quest) - :line-length *max-line-items*)) - (unless (quest-infinite quest) - (remove-object-attribute npc 'quest npc)))))))) + (unless (zerop (length (npc-quest npc))) + (quest player npc)))) + +(defun quest (player npc) + "Handle NPC quests" + (let ((quest (get-game-object 'quest (npc-quest npc))) + (npc-name (npc-name npc))) + (unless quest (format t "~&This NPC doesn't have a quest!") + (return-from quest)) + (if (dolist (i (quest-proof-item quest)) + (unless (member i (player-item player) :test #'equalp) + (return T))) + (when (y-or-n-p "~%~A has a quest. Accept it?" npc-name) + (format t "~&~A: ~A" (string-upcase npc-name) + (quest-say-before quest))) + (when (y-or-n-p "~%Give to ~A: ~A?" npc-name + (string-from-list (quest-proof-item quest) :sep ", " + :line-length *max-line-items*)) + (dolist (j (quest-proof-item quest)) + (remove-object-attribute player 'item j)) + (dolist (k (quest-reward-item quest)) + (set-object-attribute player 'item k)) + (add-player-experience player (quest-experience quest)) + (add-player-money player (quest-money quest)) + (format t "~&~A: ~A" (string-upcase npc-name) + (quest-say-after quest)) + (format t "~&~%Quest complete. You gain:") + (format t "~&Money: ~A Experience: ~A~&Items: ~A" + (quest-money quest) (quest-experience quest) + (string-from-list (quest-reward-item quest) + :line-length *max-line-items*)) + (unless (quest-infinite quest) + (remove-object-attribute npc 'quest npc)))))) (defun trade (player npc) "The player trades with this NPC" + ;; XXX This is no longer a game command - remove the leading check? (when (and (stringp npc) (member npc (place-npc (get-game-object 'place (player-place player))) @@ -364,6 +362,7 @@ (unless item-name (format t "~&Please specify an item to pick up!") (return-from take)) + ;; TODO Insert fuzzy-match (let ((place (get-game-object 'place (player-place player))) (item-name (string-capitalize item-name)) (item (get-game-object 'item item-name))) @@ -390,6 +389,7 @@ (format t "~&Please specify an item to drop!") (return-from drop)) (setf item (string-capitalize item)) + ;; TODO Insert fuzzy-match (if (member item (player-item player) :test #'equalp) (progn (remove-object-attribute player 'item item) @@ -408,6 +408,7 @@ (defun equip (player &optional new-weapon) "The player sets another item to be his weapon" ;;XXX Replace this with 'hold'? (Also possible for non-weapons.) + ;; TODO Insert fuzzy-match (unless new-weapon (format t "~&Please specify a weapon to be equipped!") (return-from equip)) @@ -429,6 +430,7 @@ (unless opponent (format t "~&Please specify an opponent!") (return-from attack)) + ;; TODO Insert fuzzy-match (unless (member opponent (list-place-objects 'monster (get-game-object 'place (player-place player))) diff --git a/lisp/util.lisp b/lisp/util.lisp index e7fd39c..e750c6b 100644 --- a/lisp/util.lisp +++ b/lisp/util.lisp @@ -197,25 +197,26 @@ (if (zerop (length seq)) NIL (elt seq (random (length seq))))) -(defun fuzzy-match (pattern lst &key (test #'equalp)) +(defun fuzzy-match (pattern lst &key (strict NIL) (test #'equalp)) "Return the element of a list of strings that best matches the input pattern" ;; An element whose start matches the pattern is a better fit than an element - ;; with a match in the middle. If there are multiple equally well-fitting - ;; elements, the search is inconclusive and NIL is returned. - (do* ((result NIL) (multiple NIL) (start-match NIL) (l lst (cdr l)) + ;; with a match in the middle. If :strict is T, only starting matches are + ;; considered. If there are multiple equally well-fitting elements, the search + ;; is inconclusive and NIL is returned. + (do* ((result NIL) (multiple-matches NIL) (start-match NIL) (l lst (cdr l)) (next (search pattern (first l) :test test) (search pattern (first l) :test test))) - ((null l) (if multiple NIL result)) - (when next + ((null l) (if multiple-matches NIL result)) + (when (and next (or (not strict) (and strict (zerop next)))) (if result (if (zerop next) (if start-match (return-from fuzzy-match) (progn (setf result (first l)) (setf start-match T) - (setf multiple NIL))) + (setf multiple-matches NIL))) (unless start-match - (setf multiple T))) + (setf multiple-matches T))) (progn (setf result (first l)) (setf start-match (zerop next))))))) @@ -314,7 +315,7 @@ (defun clear-screen () "Clear the screen in an OS-dependent manner" ;; NOTE: only works with CLISP! (ext:shell function used) - ;; TODO Make sure we're on clisp, otherwise do nothing + ;; Causes an error on other implementations (cond ((member ':unix *features*) (ext:shell "clear")) ((member ':win32 *features*) (ext:shell "cls")) (t (debugging "~&clear-screen is not supported on this operating system!"))))