-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathevolution.lisp
140 lines (124 loc) · 3.36 KB
/
evolution.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
(load "ergolib/init")
(require :ergolib)
(define-synonym add! add)
(define-synonym set! setf)
(define-synonym dec! decf)
(define-synonym inc! incf)
(define-synonym display princ)
(define-synonym equal? equal)
(define-synonym push! push)
(define-synonym zero? zerop)
(define-synonym del! del)
(defc width 100)
(defc height 30)
(defc jungle '(45 10 10 10))
(defc plant-energy 80)
(defv plants (make-set))
(defun random-plant (left top width height)
(bb pos (cons (+ left (random width)) (+ top (random height)))
(add! plants pos)
))
(defun add-plants ()
(apply #'random-plant jungle)
(random-plant 0 0 width height)
)
(defstruct animal x y energy dir genes)
(defv animals
(list (make-animal :x (ash width -1)
:y (ash height -1)
:energy 1000
:dir 0
:genes (loop repeat 8 collecting
(1+ (random 10))
))))
(define-method (move! (_ animal dir x y energy))
(set! x
(mod (+ x
(mcond
(and (>= dir 2) (< dir 5)) 1
(or (= dir 1) (= dir 5)) 0
-1)
width)
width))
(set! y
(mod (+ y
(mcond
(and (>= dir 0) (< dir 3)) -1
(and (>= dir 4) (< dir 7)) 1
0)
height)
height))
(dec! energy)
)
(define-method (turn! (_ animal dir genes))
(bb x (random (apply #'+ genes))
(bb :fn angle (genes x)
(bb xnu (- x (car genes))
(if (< xnu 0)
0
(1+ (angle (cdr genes) xnu))
))
(set! dir (mod (+ dir (angle genes x)) 8))
)))
(define-method (eat! (_ animal x y energy))
(bb pos (cons x y)
(when (member? plants pos)
(inc! energy plant-energy)
(del! plants pos)
)))
(defc reproduction-energy 200)
(define-method (reproduce! (animal animal energy genes))
(when (>= energy reproduction-energy)
(set! energy (ash energy -1))
(bb animal-nu (copy-structure animal)
genes (copy-list genes)
mutation (random 8)
(set! (ref genes mutation)
(max 1 (+ (ref genes mutation) (random 3) -1)))
(set! (animal-genes animal-nu) genes)
(push! animal-nu animals)
)))
(defun update-world ()
(set! animals (remove-if (fn (animal)
(<= (animal-energy animal) 0))
animals))
(for animal in animals do
(turn! animal)
(move! animal)
(eat! animal)
(reproduce! animal)
)
(add-plants)
)
(defun draw-world ()
(loop for y below height do (progn
(fresh-line)
(display "|")
(loop for x below width do
(display (mcond
(some (fn (animal)
(and (= (animal-x animal) x)
(= (animal-y animal) y)))
animals)
#\M
(member? plants (cons x y))
#\*
#\space)))
(display "|")
)))
(defun evolution ()
(draw-world)
(fresh-line)
(bb str (read-line)
(if (equal? str "quit")
()
(bb x (parse-integer str :junk-allowed t)
(if x
(loop for i below x do
(update-world)
if (zero? (mod i 1000)) do
(display #\.))
(update-world)
)
(evolution)
))))