Newer
Older
naledi / player.lisp
;;;;
;;;; 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))))