diff --git a/items.lisp b/items.lisp index e0b1769..582a4a1 100644 --- a/items.lisp +++ b/items.lisp @@ -6,15 +6,20 @@ ;;;; (c) 2018 Daniel Vedder, MIT license ;;;; +;;TODO This needs to be done with CLOS + (defstruct item (name "") (description "") (weight 0) (movable T) (occupant NIL) + (equipment NIL) + (resource NIL) (destroy-with '()) (drops '()) - (craft-with '())) + (craft-with '()) + (action #'(lambda () NIL))) (let ((item-list NIL)) (defun register-item (symbol-name item-object) diff --git a/items.lisp b/items.lisp index e0b1769..582a4a1 100644 --- a/items.lisp +++ b/items.lisp @@ -6,15 +6,20 @@ ;;;; (c) 2018 Daniel Vedder, MIT license ;;;; +;;TODO This needs to be done with CLOS + (defstruct item (name "") (description "") (weight 0) (movable T) (occupant NIL) + (equipment NIL) + (resource NIL) (destroy-with '()) (drops '()) - (craft-with '())) + (craft-with '()) + (action #'(lambda () NIL))) (let ((item-list NIL)) (defun register-item (symbol-name item-object) diff --git a/player.lisp b/player.lisp new file mode 100644 index 0000000..d6e8e7d --- /dev/null +++ b/player.lisp @@ -0,0 +1,77 @@ +;;;; +;;;; Terra Nostra is a Minecraft-like survival game for the commandline. +;;;; +;;;; This file is responsible for managing the player instance. +;;;; +;;;; (c) 2018 Daniel Vedder, MIT license +;;;; + +(defparameter *player* NIL) + +(defstruct player + (name "") + (strength 0) + (dexterity 0) + (intelligence 0) + (experience 0) + (level 0) + (hunger 0) + (health 0) + (equipment NIL) + (inventory '((NIL 0) (NIL 0) (NIL 0) (NIL 0) (NIL 0) + (NIL 0) (NIL 0) (NIL 0) (NIL 0) (NIL 0)))) + + +;; INVENTORY HANDLING FUNCTIONS + +(defun stock-size (resource &optional (player *player*)) + "How many items of this resource type is the player carrying?" + (dolist (i (player-inventory player) 0) + (when (eq (item-name (first i)) resource) + (return-from stock-size (second i))))) + +(defun weight-carried (&optional (player *player*)) + "Sum up the total weight of all items carried" + (+ (item-weight (player-equipment player)) + (reduce #'+ (mapcar #'(lambda (i) + (* (second i) (item-weight (first i))))) + (player-inventory player)))) + +(defun pickup (item &optional (player *player*)) + "Add the item object to the inventory" + ;;Can the item be picked up at all? + (unless (item-movable item) + (notify "This item cannot be picked up.") + (return-from pickup)) + ;;Is the player strong enough to pick this up? + (unless (<= (+ (item-weight item) (weight-carried player)) + (* (player-strength player) 20)) ;XXX magic number + (notify "You are too burdened to pick this up.") + (return-from pickup)) + (dolist (inv (player-inventory player)) + ;;Resources may be stacked + (when (and (item-resource item) + (eq (item-name item) (item-name (first inv)))) + (incf (second inv)) + (notify "You have picked up one ~A." (item-name item)) + (return-from pickup)) + ;;Deposit the item in an empty slot + (when (and (null (first inv)) (item-resource item) ;normal pickup + ;;XXX replace with find-if + (zerop (count-instances (item-name item) + (mapcar #'(lambda (i) (item-name (car i))))))) + (setf inv (list item 1)) + (notify "You have picked up one ~A." (item-name item)) + (return-from pickup))) + ;;If nothing has worked, the inventory is full + (notify "Your inventory is full.")) + +(defun drop (inv-nr &optional (player *player)) + "Drop an item from the given inventory index" + ;;TODO add item back to patch + (let* ((item-entry (nth inv-nr (player-inventory player))) + (item (when item-entry (first item-entry)))) + (if (and item (> (stock-size (item-name item) 1))) + (decf (second item-entry)) + (setf item NIL (second item-entry) 0)))) + diff --git a/items.lisp b/items.lisp index e0b1769..582a4a1 100644 --- a/items.lisp +++ b/items.lisp @@ -6,15 +6,20 @@ ;;;; (c) 2018 Daniel Vedder, MIT license ;;;; +;;TODO This needs to be done with CLOS + (defstruct item (name "") (description "") (weight 0) (movable T) (occupant NIL) + (equipment NIL) + (resource NIL) (destroy-with '()) (drops '()) - (craft-with '())) + (craft-with '()) + (action #'(lambda () NIL))) (let ((item-list NIL)) (defun register-item (symbol-name item-object) diff --git a/player.lisp b/player.lisp new file mode 100644 index 0000000..d6e8e7d --- /dev/null +++ b/player.lisp @@ -0,0 +1,77 @@ +;;;; +;;;; Terra Nostra is a Minecraft-like survival game for the commandline. +;;;; +;;;; This file is responsible for managing the player instance. +;;;; +;;;; (c) 2018 Daniel Vedder, MIT license +;;;; + +(defparameter *player* NIL) + +(defstruct player + (name "") + (strength 0) + (dexterity 0) + (intelligence 0) + (experience 0) + (level 0) + (hunger 0) + (health 0) + (equipment NIL) + (inventory '((NIL 0) (NIL 0) (NIL 0) (NIL 0) (NIL 0) + (NIL 0) (NIL 0) (NIL 0) (NIL 0) (NIL 0)))) + + +;; INVENTORY HANDLING FUNCTIONS + +(defun stock-size (resource &optional (player *player*)) + "How many items of this resource type is the player carrying?" + (dolist (i (player-inventory player) 0) + (when (eq (item-name (first i)) resource) + (return-from stock-size (second i))))) + +(defun weight-carried (&optional (player *player*)) + "Sum up the total weight of all items carried" + (+ (item-weight (player-equipment player)) + (reduce #'+ (mapcar #'(lambda (i) + (* (second i) (item-weight (first i))))) + (player-inventory player)))) + +(defun pickup (item &optional (player *player*)) + "Add the item object to the inventory" + ;;Can the item be picked up at all? + (unless (item-movable item) + (notify "This item cannot be picked up.") + (return-from pickup)) + ;;Is the player strong enough to pick this up? + (unless (<= (+ (item-weight item) (weight-carried player)) + (* (player-strength player) 20)) ;XXX magic number + (notify "You are too burdened to pick this up.") + (return-from pickup)) + (dolist (inv (player-inventory player)) + ;;Resources may be stacked + (when (and (item-resource item) + (eq (item-name item) (item-name (first inv)))) + (incf (second inv)) + (notify "You have picked up one ~A." (item-name item)) + (return-from pickup)) + ;;Deposit the item in an empty slot + (when (and (null (first inv)) (item-resource item) ;normal pickup + ;;XXX replace with find-if + (zerop (count-instances (item-name item) + (mapcar #'(lambda (i) (item-name (car i))))))) + (setf inv (list item 1)) + (notify "You have picked up one ~A." (item-name item)) + (return-from pickup))) + ;;If nothing has worked, the inventory is full + (notify "Your inventory is full.")) + +(defun drop (inv-nr &optional (player *player)) + "Drop an item from the given inventory index" + ;;TODO add item back to patch + (let* ((item-entry (nth inv-nr (player-inventory player))) + (item (when item-entry (first item-entry)))) + (if (and item (> (stock-size (item-name item) 1))) + (decf (second item-entry)) + (setf item NIL (second item-entry) 0)))) + diff --git a/terranostra.lisp b/terranostra.lisp index 6dfb61f..e08a41b 100644 --- a/terranostra.lisp +++ b/terranostra.lisp @@ -113,9 +113,9 @@ (defun notify (news-string) "Append a string to the news to notify the user." + ;;FIXME This needs to support (format) (setf news (cons news-string news))) - (defun message-window () "Return a dialog window with the last game messages." (make-instance 'dialog-window