Newer
Older
naledi / server / item-methods.lisp
;;;;
;;;; Naledi ya Africa ("Star of Africa") is an ncurses-based survival game
;;;; set in Africa.
;;;;
;;;; This file defines all CLOS methods used in the game for the different
;;;; item classes (human methods are separate in player.lisp).
;;;; 
;;;; (c) 2018 Daniel Vedder, MIT license
;;;;

(in-package :naledi-ya-africa)

(defmethod move ((a animal) dir)
	"An animal moves one space in the specified direction, if possible"
	(let* ((here (coord (.x a) (.y a)))
			  (target (coordsindir (.x a) (.y a) dir))
			  (target-patch (coord (first target) (second target))))
		;;XXX more conditions?
		(cond ((null target-patch)
				  (logf 3 "~S is attempting to move out of bounds ~S" a target)
				  'OUT-OF-BOUNDS)
			((patch-occupant target-patch)
				(logf 3 "~S is moving onto occupied patch ~S (~S)"
					a target (patch-occupant target-patch))
				'PATCH-OCCUPIED)
			(T (setf (patch-occupant here) NIL)
				(setf (patch-occupant target-patch) a)
				(setf (.x a) (first target) (.y a) (second target))
				T))))

;; Default `update' and `action' methods are NOP
(defmethod update ((i item)))
(defmethod action ((i item)))

(defmethod attack ((d destructable) (tl tool))
	"Attack a destructable item with a tool or weapon"
	;;Returns either the damaged item or the items it drops when destroyed
	(if (member (class-of tl) (.destructors d))
		(if (>= 0 (decf (.health d) (random (* 10 (.level tl)))))
			(.drops d) d)
		(progn (notify "You cannot attack ~A with ~A." ;;FIXME remove `notify'
				   (leading-vowl (.name d)) (leading-vowel (.name tl)))
			NIL)))

;;TODO (defmethod attack ((at attacker) (f feature) (tl tool)))
;;TODO (defmethod attack ((at attacker) (an animal) (w weapon)))

(defmethod update ((a animal))
	(when (> (age-of-the-world) (.last-move a))
		(random-move a)
		(incf (.last-move a))))

(defmethod habitat-p ((a animal) b)
	"Is the biome b a possible habitat of animal a?"
	;;XXX Don't quite like this, but it works
	(when (eq (.habitat a) T)
		(return-from habitat-p T))
	(dolist (h (.habitat a))
		(when (equalp (symbol-to-string h) (biome-name b))
			(return T))))

(defmethod random-move ((a animal))
	"Move in a random direction within the species' habitat niche"
	(do* ((dir (random-elt *directions*) (random-elt *directions*))
			 (next-patch (patchindir (.x a) (.y a) dir)
				 (patchindir (.x a) (.y a) dir))
			 (ttl 10 (1- ttl)))
		((zerop ttl) NIL)
		(when (and next-patch (null (patch-occupant next-patch))
				  (habitat-p a (patch-biome next-patch)))
			(move a dir)
			(return-from random-move a))))