Newer
Older
naledi / data.lisp
;;;;
;;;; Naledi ya Africa ("Star of Africa") is a rogue-like survival game
;;;; set in Africa.
;;;;
;;;; This file stores all game data.
;;;;
;;;; (c) 2018 Daniel Vedder, MIT license
;;;;

;;; PATCHES

(let ((world NIL))
	(defun set-world (w) (setf world w))

	(defun world-size () (length world))

	(defun save-topography (file-name) ;XXX (re)move this?
		"Save the world topography as a text file"
		(debugging "~&Saving world to file ~A" file-name) ;debug
		(with-open-file (tf file-name :direction :output)
			(dolist (row world)
				(format stream "~&~A~%"
					(string-from-list
						(mapcar #'(lambda (p)
									  (biome-char (patch-biome p)))
							row) "")))))
	
	(defun coord (x y)
		"Return the patch at the given coordinates or NIL if out of bounds"
		(unless (or (< x 0) (< y 0) (> x (length world)) (> y (length world)))
			(nth x (nth y world)))))

;;; BIOMES

(let ((biome-list NIL))
	(defun register-biome (symbol-name biome-object)
		(setf biome-list (cons (list symbol-name biome-object) biome-list)))

	(defun available-biomes ()
		(keys biome-list))

	(defun get-biome (symbol-name)
		(cassoc symbol-name biome-list)))

(defmacro new-biome (name &body body)
	`(register-biome ',name
		 (make-biome
			 :name ,(symbol-to-string name)
			 ,@body)))

;;; ITEMS

(let ((item-list NIL))
	(defun register-item (symbol-name item-object)
		(setf item-list
			(cons (list symbol-name item-object) item-list)))

	(defun get-item-type (symbol-name)
		(cassoc symbol-name item-list))

	(defun get-item (symbol-name)
		;;FIXME copy-item doesn't work with CLOS
		(copy-item (get-item-type symbol-name))))

(defmacro new-item (type name &body body)
	`(register-item ',name
		 (make-instance ',type
			 :name ,(symbol-to-string name)
			 ,@body)))

;;; ANIMALS & SPECIES

(let ((species-list NIL))
	(defun register-species (symbol-name species-object)
		(setf species-list
			(cons (list symbol-name species-object) species-list)))

	(defun get-species (symbol-name)
		(cassoc symbol-name species-list)))

(defmacro new-species (name &body body)
	`(register-species ',name
		 (make-instance 'species
			 :name ,(symbol-to-string name)
			 ,@body)))

(let ((max-id 0) (animals NIL))
	(defun add-animal (species position)
		"Create a new animal of the given species"
		(let ((a (make-animal :id max-id
					 :pos position :species species
					 :health (.max-health species))))
			(incf max-id)
			(setf animals (append animals a))))

	(defun get-animal (id)
		"Return the animal with this ID number"
		(dolist (a animals)
			(when (= (.id a) id)
				(return-from get-animal a))))

	(defun remove-animal (id)
		"Remove the animal with this ID from the game"
		;;XXX Can't we just do this with `remove-if'?
		(do ((al animals (cdr al)))
			((null al))
			(when (= (.id (car al)) id)
				(setf (cdr al) (cddr al))))))