最有意思的就是其中的genes,不同的动物会有不同的genes还会遗传和变异!!!
mapc和mapcar的区别查了一下,mapc返回原始的list而mapcar会把结果cons,如果是利用side effect话mapc比较省时间.
还有一个问题,就是对于下面的代码
(defparameter *list* '(1 2 3 4)) (mapc (lambda (x) (incf x)) *list*)
我原本以为会直接把*list*上的每一个数都加一但是并没有,mapcar也一样
但是下面的代码却可以把每一个list元素中的第一个数改变
(defparameter *l* '((1 2) (2 3) (3 4))) (mapc (lambda (x) (incf (car x))) *l*)
我想会不会是这一章前面提到过的浅复制的原因,对于symbol和integer等这些简单的元素传参数时是完全复制,没有共享的结构
但是对于后者传的是个list,是共享的.所以side effec会影响原始的值
;;;; (defparameter *width* 100) (defparameter *height* 30) (defparameter *jungle* '(45 10 10 10)) (defparameter *plant-energy* 80) ;;;;growing plants in our world (defparameter *plants* (make-hash-table :test #'equal)) (defun random-plant (left top width height) (let ((pos (cons (+ left (random width)) (+ top (random height))))) (setf (gethash pos *plants*) t))) (defun add-plants () (apply #'random-plant *jungle*) (random-plant 0 0 *width* *height*)) ;;;;create animals (defstruct animal x y energy dir genes) (defparameter *animals* (list (make-animal :x (ash *width* -1) :y (ash *height* -1) :energy 1000 :dir 0 :genes (loop repeat 8 collecting (1+ (random 10)))))) ;;;;handling animal motion (defun move (animal) (let ((dir (animal-dir animal)) (x (animal-x animal)) (y (animal-y animal))) (setf (animal-x animal) (mod (+ x (cond ((and (>= dir 2) (< dir 5)) 1) ((or (= dir 1) (= dir 5)) 0) (t -1)) *width*) *width*)) (setf (animal-y animal) (mod (+ y (cond ((and (>= dir 0) (< dir 3)) -1) ((and (>= dir 4) (< dir 7)) 1) (t 0)) *height*) *height*)) (decf (animal-energy animal)))) ;;;;handling animal turning (defun turn (animal) (let ((x (random (apply #'+ (animal-genes animal))))) (labels ((angle (genes x) (let ((xnu (- x (car genes)))) (if (< xnu 0) 0 (1+ (angle (cdr genes) xnu)))))) (setf (animal-dir animal) (mod (+ (animal-dir animal) (angle (animal-genes animal) x)) 8))))) ;;;;handling animal eating (defun eat (animal) (let ((pos (cons (animal-x animal) (animal-y animal)))) (when (gethash pos *plants*) (incf (animal-energy animal) *plant-energy*) (remhash pos *plants*)))) ;;;;handling animal reproduction (defparameter *reproduction-energy* 200) (defun reproduce (animal) (let ((e (animal-energy animal))) (when (>= e *reproduction-energy*) (setf (animal-energy animal) (ash e -1)) (let ((animal-nu (copy-structure animal)) (genes (copy-list (animal-genes animal))) (mutation (random 8))) (setf (nth mutation genes) (max 1 (+ (nth mutation genes) (random 3) -1))) (setf (animal-genes animal-nu) genes) (push animal-nu *animals*))))) ;;;;simulating a day in our world (defun update-world () (setf *animals* (remove-if (lambda (animal) (<= (animal-energy animal) 0)) *animals*)) (mapc (lambda (animal) (turn animal) (move animal) (eat animal) (reproduce animal)) *animals*) (add-plants)) ;;;;drawing our world (defun draw-world () (loop for y below *height* do (progn (fresh-line) (princ "|") (loop for x below *width* do (princ (cond ((some (lambda (animal) (and (= (animal-x animal) x) (= (animal-y animal) y))) *animals*) #M) ((gethash (cons x y) *plants*) #*) (t #space)))) (princ "|")))) ;;;;creating a user interface (defun evolution () (draw-world) (fresh-line) (let ((str (read-line))) (cond ((equal str "quit") ()) (t (let ((x (parse-integer str :junk-allowed t))) (if x (loop for i below x do (update-world) if (zerop (mod i 1000)) do (princ #.)) (update-world)) (evolution))))))