diff --git a/ATL/atl-mode.el b/ATL/atl-mode.el index 598c28c..78d462c 100644 --- a/ATL/atl-mode.el +++ b/ATL/atl-mode.el @@ -13,8 +13,7 @@ ;; define commands '("define-place" "define-item" "define-monster" "define-npc" "define-race" "define-place" "define-weapon" - "define-class" "name-world" "load-file" - "start-place" "start-money") + "define-class" "define-player" "name-world" "load-file") '() ;; other commands (adjust this?) '("\\.atl$") ;; files for which to activate this mode '(linum-mode) ;; other functions to call diff --git a/ATL/atl-mode.el b/ATL/atl-mode.el index 598c28c..78d462c 100644 --- a/ATL/atl-mode.el +++ b/ATL/atl-mode.el @@ -13,8 +13,7 @@ ;; define commands '("define-place" "define-item" "define-monster" "define-npc" "define-race" "define-place" "define-weapon" - "define-class" "name-world" "load-file" - "start-place" "start-money") + "define-class" "define-player" "name-world" "load-file") '() ;; other commands (adjust this?) '("\\.atl$") ;; files for which to activate this mode '(linum-mode) ;; other functions to call diff --git a/ATL/lisp-test.atl b/ATL/lisp-test.atl index a89aa59..b68d944 100644 --- a/ATL/lisp-test.atl +++ b/ATL/lisp-test.atl @@ -4,6 +4,12 @@ name-world "Underworld" +define-player "Start" + money 200 + place "Fields of Punishment" + max-health 50 + health 50 + define-place "Nowhere" description "Welcome to Nowhere! You are in the void, the space between the worlds. Around you is black. @@ -43,6 +49,3 @@ load-file races-classes.atl load-file game-objects.atl load-file creator-test.atl - -start-place "Styx" -start-money 50 \ No newline at end of file diff --git a/ATL/atl-mode.el b/ATL/atl-mode.el index 598c28c..78d462c 100644 --- a/ATL/atl-mode.el +++ b/ATL/atl-mode.el @@ -13,8 +13,7 @@ ;; define commands '("define-place" "define-item" "define-monster" "define-npc" "define-race" "define-place" "define-weapon" - "define-class" "name-world" "load-file" - "start-place" "start-money") + "define-class" "define-player" "name-world" "load-file") '() ;; other commands (adjust this?) '("\\.atl$") ;; files for which to activate this mode '(linum-mode) ;; other functions to call diff --git a/ATL/lisp-test.atl b/ATL/lisp-test.atl index a89aa59..b68d944 100644 --- a/ATL/lisp-test.atl +++ b/ATL/lisp-test.atl @@ -4,6 +4,12 @@ name-world "Underworld" +define-player "Start" + money 200 + place "Fields of Punishment" + max-health 50 + health 50 + define-place "Nowhere" description "Welcome to Nowhere! You are in the void, the space between the worlds. Around you is black. @@ -43,6 +49,3 @@ load-file races-classes.atl load-file game-objects.atl load-file creator-test.atl - -start-place "Styx" -start-money 50 \ No newline at end of file diff --git a/lisp/interpreter.lisp b/lisp/interpreter.lisp index 03d4886..7adfbb5 100644 --- a/lisp/interpreter.lisp +++ b/lisp/interpreter.lisp @@ -33,21 +33,12 @@ (defcommand define-place place) (defcommand define-race race) (defcommand define-class character-class) +(defcommand define-player player) (defcommand define-monster monster) (defcommand define-weapon weapon) (defcommand define-item item) (defcommand define-npc npc) -(defun start-place (place) - (debugging "~&Starting place is ~A" place) - (setf (world-starting-place *world*) place) - NIL) - -(defun start-money (amount) - (debugging "~&Starting money is ~A gold pieces" amount) - (setf (world-starting-money *world*) amount) - NIL) - (let ((world-directory NIL) (loaded-files NIL)) diff --git a/ATL/atl-mode.el b/ATL/atl-mode.el index 598c28c..78d462c 100644 --- a/ATL/atl-mode.el +++ b/ATL/atl-mode.el @@ -13,8 +13,7 @@ ;; define commands '("define-place" "define-item" "define-monster" "define-npc" "define-race" "define-place" "define-weapon" - "define-class" "name-world" "load-file" - "start-place" "start-money") + "define-class" "define-player" "name-world" "load-file") '() ;; other commands (adjust this?) '("\\.atl$") ;; files for which to activate this mode '(linum-mode) ;; other functions to call diff --git a/ATL/lisp-test.atl b/ATL/lisp-test.atl index a89aa59..b68d944 100644 --- a/ATL/lisp-test.atl +++ b/ATL/lisp-test.atl @@ -4,6 +4,12 @@ name-world "Underworld" +define-player "Start" + money 200 + place "Fields of Punishment" + max-health 50 + health 50 + define-place "Nowhere" description "Welcome to Nowhere! You are in the void, the space between the worlds. Around you is black. @@ -43,6 +49,3 @@ load-file races-classes.atl load-file game-objects.atl load-file creator-test.atl - -start-place "Styx" -start-money 50 \ No newline at end of file diff --git a/lisp/interpreter.lisp b/lisp/interpreter.lisp index 03d4886..7adfbb5 100644 --- a/lisp/interpreter.lisp +++ b/lisp/interpreter.lisp @@ -33,21 +33,12 @@ (defcommand define-place place) (defcommand define-race race) (defcommand define-class character-class) +(defcommand define-player player) (defcommand define-monster monster) (defcommand define-weapon weapon) (defcommand define-item item) (defcommand define-npc npc) -(defun start-place (place) - (debugging "~&Starting place is ~A" place) - (setf (world-starting-place *world*) place) - NIL) - -(defun start-money (amount) - (debugging "~&Starting money is ~A gold pieces" amount) - (setf (world-starting-money *world*) amount) - NIL) - (let ((world-directory NIL) (loaded-files NIL)) diff --git a/lisp/player.lisp b/lisp/player.lisp index 0cbe51b..b6988c7 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -49,6 +49,15 @@ (special-ability NIL)) +(defun add-player (player) + "Add this player to the game world" + (when (null (list-world-objects 'player)) + (setf (player-game-admin player) T)) + (add-game-object player) + (set-object-attribute (get-game-object 'place (player-place player)) + 'player (player-name player)) + (objectify-place-monsters (player-place player))) + ;; XXX This function is probably superfluous, as the player struct should only ;; store names of game objects (the actual objects are stored in *world*) (let ((list-function (make-list-function 'player NIL))) diff --git a/ATL/atl-mode.el b/ATL/atl-mode.el index 598c28c..78d462c 100644 --- a/ATL/atl-mode.el +++ b/ATL/atl-mode.el @@ -13,8 +13,7 @@ ;; define commands '("define-place" "define-item" "define-monster" "define-npc" "define-race" "define-place" "define-weapon" - "define-class" "name-world" "load-file" - "start-place" "start-money") + "define-class" "define-player" "name-world" "load-file") '() ;; other commands (adjust this?) '("\\.atl$") ;; files for which to activate this mode '(linum-mode) ;; other functions to call diff --git a/ATL/lisp-test.atl b/ATL/lisp-test.atl index a89aa59..b68d944 100644 --- a/ATL/lisp-test.atl +++ b/ATL/lisp-test.atl @@ -4,6 +4,12 @@ name-world "Underworld" +define-player "Start" + money 200 + place "Fields of Punishment" + max-health 50 + health 50 + define-place "Nowhere" description "Welcome to Nowhere! You are in the void, the space between the worlds. Around you is black. @@ -43,6 +49,3 @@ load-file races-classes.atl load-file game-objects.atl load-file creator-test.atl - -start-place "Styx" -start-money 50 \ No newline at end of file diff --git a/lisp/interpreter.lisp b/lisp/interpreter.lisp index 03d4886..7adfbb5 100644 --- a/lisp/interpreter.lisp +++ b/lisp/interpreter.lisp @@ -33,21 +33,12 @@ (defcommand define-place place) (defcommand define-race race) (defcommand define-class character-class) +(defcommand define-player player) (defcommand define-monster monster) (defcommand define-weapon weapon) (defcommand define-item item) (defcommand define-npc npc) -(defun start-place (place) - (debugging "~&Starting place is ~A" place) - (setf (world-starting-place *world*) place) - NIL) - -(defun start-money (amount) - (debugging "~&Starting money is ~A gold pieces" amount) - (setf (world-starting-money *world*) amount) - NIL) - (let ((world-directory NIL) (loaded-files NIL)) diff --git a/lisp/player.lisp b/lisp/player.lisp index 0cbe51b..b6988c7 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -49,6 +49,15 @@ (special-ability NIL)) +(defun add-player (player) + "Add this player to the game world" + (when (null (list-world-objects 'player)) + (setf (player-game-admin player) T)) + (add-game-object player) + (set-object-attribute (get-game-object 'place (player-place player)) + 'player (player-name player)) + (objectify-place-monsters (player-place player))) + ;; XXX This function is probably superfluous, as the player struct should only ;; store names of game objects (the actual objects are stored in *world*) (let ((list-function (make-list-function 'player NIL))) diff --git a/lisp/ui.lisp b/lisp/ui.lisp index 7d0c25d..8ecdf8c 100644 --- a/lisp/ui.lisp +++ b/lisp/ui.lisp @@ -2,30 +2,25 @@ ;;; Atlantis is a framework for creating multi-user dungeon worlds. ;;; This is the Common Lisp implementation. ;;; -;;; The client module is responsible for the actual user interface presented -;;; to a player. (Warning: this will likely change significantly, currently -;;; I am only implementing a mock-up before I get the networking part working.) +;;; This module is responsible for the interactive user interface. All +;;; in-game UI should be done here. (Pre-game UI goes into atlantis.lisp.) +;;; Currently, it also does quite a bit of game logic - perhaps that should +;;; be changed later. ;;; ;;; Licensed under the terms of the MIT license. ;;; author: Daniel Vedder ;;; date: 21/05/2015 ;;; -(let ((player NIL)) - (defun play-game (player-name) - "The main game loop" + +(defun play-game (player-name) + "The main game loop" + (let ((player (get-game-object 'player player-name))) (clear-screen) ;; Initialize the player if necessary (when (null player) - (setf player (get-game-object 'player player-name))) - (when (null player) (setf player (create-player player-name)) - (when (null (list-world-objects 'player)) - (setf (player-game-admin player) T)) - (add-game-object player) - (set-object-attribute (get-game-object 'place (player-place player)) - 'player (player-name player))) - (objectify-place-monsters (player-place player)) + (add-player player)) ;; The actual game loop (clear-screen) (let ((place (get-game-object 'place (player-place player)))) @@ -39,14 +34,15 @@ (defun create-player (player-name) "The user creates a new player" ;; XXX This function feels somewhat ugly - any possibility of a cleanup? - (let ((player (make-player :name player-name - :place (world-starting-place *world*) - :money (world-starting-money *world*))) - (char-attr - '((strength 0) (dexterity 0) - (constitution 0) (intelligence 0))) - (items NIL) (weapon "") - (character-points NIL)) + (let* ((start-player (get-game-object 'player "Start")) + (player (if start-player (copy-player start-player) + (make-player :name player-name + :place (random-elt (list-world-objects 'place))))) + (char-attr + '((strength 0) (dexterity 0) + (constitution 0) (intelligence 0))) + (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)) ;; Chose race and class @@ -68,7 +64,7 @@ you may assign one number to each of the following attributes:") (format t "~&~A~%~A~%~%The numbers are:" text (string-from-list (keys char-attr))) - ;; TODO I should replace simple-input with something offering 'magic' + ;; XXX I should replace simple-input with something offering 'magic' (?) (do* ((i 0 (1+ i)) (attr (safe-nth i (keys char-attr)) (safe-nth i (keys char-attr))) (val (cassoc attr char-attr) (cassoc attr char-attr))) @@ -196,7 +192,7 @@ (defun goto (player &optional location) "Go to the specified location" - ;; Look before you leap + ;; Look before you leap ;-) (unless location (format t "~&Please specify a location!") (return-from goto)) @@ -345,6 +341,7 @@ (defun attack (player &optional opponent) "The player launches an attack at a monster" + ;; FIXME Still gives problems (usually, neither opponent hits) (unless opponent (format t "~&Please specify an opponent!") (return-from attack)) diff --git a/ATL/atl-mode.el b/ATL/atl-mode.el index 598c28c..78d462c 100644 --- a/ATL/atl-mode.el +++ b/ATL/atl-mode.el @@ -13,8 +13,7 @@ ;; define commands '("define-place" "define-item" "define-monster" "define-npc" "define-race" "define-place" "define-weapon" - "define-class" "name-world" "load-file" - "start-place" "start-money") + "define-class" "define-player" "name-world" "load-file") '() ;; other commands (adjust this?) '("\\.atl$") ;; files for which to activate this mode '(linum-mode) ;; other functions to call diff --git a/ATL/lisp-test.atl b/ATL/lisp-test.atl index a89aa59..b68d944 100644 --- a/ATL/lisp-test.atl +++ b/ATL/lisp-test.atl @@ -4,6 +4,12 @@ name-world "Underworld" +define-player "Start" + money 200 + place "Fields of Punishment" + max-health 50 + health 50 + define-place "Nowhere" description "Welcome to Nowhere! You are in the void, the space between the worlds. Around you is black. @@ -43,6 +49,3 @@ load-file races-classes.atl load-file game-objects.atl load-file creator-test.atl - -start-place "Styx" -start-money 50 \ No newline at end of file diff --git a/lisp/interpreter.lisp b/lisp/interpreter.lisp index 03d4886..7adfbb5 100644 --- a/lisp/interpreter.lisp +++ b/lisp/interpreter.lisp @@ -33,21 +33,12 @@ (defcommand define-place place) (defcommand define-race race) (defcommand define-class character-class) +(defcommand define-player player) (defcommand define-monster monster) (defcommand define-weapon weapon) (defcommand define-item item) (defcommand define-npc npc) -(defun start-place (place) - (debugging "~&Starting place is ~A" place) - (setf (world-starting-place *world*) place) - NIL) - -(defun start-money (amount) - (debugging "~&Starting money is ~A gold pieces" amount) - (setf (world-starting-money *world*) amount) - NIL) - (let ((world-directory NIL) (loaded-files NIL)) diff --git a/lisp/player.lisp b/lisp/player.lisp index 0cbe51b..b6988c7 100644 --- a/lisp/player.lisp +++ b/lisp/player.lisp @@ -49,6 +49,15 @@ (special-ability NIL)) +(defun add-player (player) + "Add this player to the game world" + (when (null (list-world-objects 'player)) + (setf (player-game-admin player) T)) + (add-game-object player) + (set-object-attribute (get-game-object 'place (player-place player)) + 'player (player-name player)) + (objectify-place-monsters (player-place player))) + ;; XXX This function is probably superfluous, as the player struct should only ;; store names of game objects (the actual objects are stored in *world*) (let ((list-function (make-list-function 'player NIL))) diff --git a/lisp/ui.lisp b/lisp/ui.lisp index 7d0c25d..8ecdf8c 100644 --- a/lisp/ui.lisp +++ b/lisp/ui.lisp @@ -2,30 +2,25 @@ ;;; Atlantis is a framework for creating multi-user dungeon worlds. ;;; This is the Common Lisp implementation. ;;; -;;; The client module is responsible for the actual user interface presented -;;; to a player. (Warning: this will likely change significantly, currently -;;; I am only implementing a mock-up before I get the networking part working.) +;;; This module is responsible for the interactive user interface. All +;;; in-game UI should be done here. (Pre-game UI goes into atlantis.lisp.) +;;; Currently, it also does quite a bit of game logic - perhaps that should +;;; be changed later. ;;; ;;; Licensed under the terms of the MIT license. ;;; author: Daniel Vedder ;;; date: 21/05/2015 ;;; -(let ((player NIL)) - (defun play-game (player-name) - "The main game loop" + +(defun play-game (player-name) + "The main game loop" + (let ((player (get-game-object 'player player-name))) (clear-screen) ;; Initialize the player if necessary (when (null player) - (setf player (get-game-object 'player player-name))) - (when (null player) (setf player (create-player player-name)) - (when (null (list-world-objects 'player)) - (setf (player-game-admin player) T)) - (add-game-object player) - (set-object-attribute (get-game-object 'place (player-place player)) - 'player (player-name player))) - (objectify-place-monsters (player-place player)) + (add-player player)) ;; The actual game loop (clear-screen) (let ((place (get-game-object 'place (player-place player)))) @@ -39,14 +34,15 @@ (defun create-player (player-name) "The user creates a new player" ;; XXX This function feels somewhat ugly - any possibility of a cleanup? - (let ((player (make-player :name player-name - :place (world-starting-place *world*) - :money (world-starting-money *world*))) - (char-attr - '((strength 0) (dexterity 0) - (constitution 0) (intelligence 0))) - (items NIL) (weapon "") - (character-points NIL)) + (let* ((start-player (get-game-object 'player "Start")) + (player (if start-player (copy-player start-player) + (make-player :name player-name + :place (random-elt (list-world-objects 'place))))) + (char-attr + '((strength 0) (dexterity 0) + (constitution 0) (intelligence 0))) + (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)) ;; Chose race and class @@ -68,7 +64,7 @@ you may assign one number to each of the following attributes:") (format t "~&~A~%~A~%~%The numbers are:" text (string-from-list (keys char-attr))) - ;; TODO I should replace simple-input with something offering 'magic' + ;; XXX I should replace simple-input with something offering 'magic' (?) (do* ((i 0 (1+ i)) (attr (safe-nth i (keys char-attr)) (safe-nth i (keys char-attr))) (val (cassoc attr char-attr) (cassoc attr char-attr))) @@ -196,7 +192,7 @@ (defun goto (player &optional location) "Go to the specified location" - ;; Look before you leap + ;; Look before you leap ;-) (unless location (format t "~&Please specify a location!") (return-from goto)) @@ -345,6 +341,7 @@ (defun attack (player &optional opponent) "The player launches an attack at a monster" + ;; FIXME Still gives problems (usually, neither opponent hits) (unless opponent (format t "~&Please specify an opponent!") (return-from attack)) diff --git a/lisp/util.lisp b/lisp/util.lisp index 3ce44e3..db3765c 100644 --- a/lisp/util.lisp +++ b/lisp/util.lisp @@ -177,6 +177,10 @@ (if (= next-elt (1- (length vector))) NIL (cons (aref vector next-elt) (to-list vector (1+ next-elt))))) +(defun random-elt (seq) + "Return a random element of this sequence" + (elt seq (random (length seq)))) + (defun load-text-file (file-name) "Load a text file into a list of strings (representing the lines)" (with-open-file (f file-name)