summaryrefslogtreecommitdiff
path: root/src/l-system.lisp
blob: d57c4199e081b29ece614992ed4663c0fb4f9a40 (plain)
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
;;;; l-system.lisp
#|
(ql:quickload :l-system)
|#

(in-package #:l-system)

;;; "l-system" goes here. Hacks and glory await!

(defun iterconcat (fn list)
  "Applies fn on each element of list, and concatenate a copy of the resulting lists."
  (iter (for item in list)
	(appending (funcall fn item))))

(defun make-case-clause (keys value)
  "Make one CASE clause mapping a list of KEYS to one VALUE"
  `((,@keys) ',value))

(defun make-case-clauses-from-rules (rules)
  "Makes a list of CASE clauses from the RULES."
  (mapcar (lambda (rule) (make-case-clause (list (first rule)) (rest rule)))
          rules))

(defun generate-l-system (rules)
  "Make lambda Lindenmayer system"
  `(lambda (atom) (case atom ,@(make-case-clauses-from-rules rules))))

(defmacro l-system (&rest rules)
  (generate-l-system rules))

(defun iter-l-system (fn seed n)
  (iter (repeat n)
	(with item = seed)
	(setf item
	      (iterconcat fn
			  item))
	(finally (return item))))

(defun eval-l-system (fn list)
  (iter (with seed = '(0 0 0))
	(for item in list)
	(appending (setf seed
			 (mapcar #'+
				 seed
				 (car (funcall fn item)))))))

#|
(iterconcat (l-system (a a i a d a)
		      (b b d b i b)
		      (i i b i a i)
		      (d d a d b d))
	    '(d)) ;; --> (D A D B D)

(iter-l-system (l-system (a a i a d a)
			 (b b d b i b)
			 (i i b i a i)
			 (d d a d b d))
	       '(d)
	       3)
;; --> (D A D B D A I A D A D A D B D B D B I B D A D B D A I A D A I B I A I A I A D
        A D A D B D A I A D A D A D B D A I A D A D A D B D B D B I B D A D B D B D B
        I B D A D B D B D B I B I B I A I B D B I B D A D B D A I A D A D A D B D B D
        B I B D A D B D)

(eval-l-system (l-system (a (0.0 1.0 0.0))
			 (b (0.0 -1.0 0.0))
			 (i (-1.0 0.0 0.0))
			 (d (1.0 0.0 0.0)))
	       (iter-l-system (l-system (a a i a d a)
			 (b b d b i b)
			 (i i b i a i)
			 (d d a d b d))
			      '(d)
			      3))
|#