updated version, but need to update installation scripts
[cls.git] / xlisponly / lsp / turtles.lsp
blobf191419c33ab306fa8e0fa14bc9f916fcb77855e
1 #-:classes (load "classes")
3 ; On an IBM PC, ANSI escape sequences probably won't work unless you use
4 ; NNANSI.SYS because the buffered output used bypasses the BIOS.
6 ; This is a sample XLISP program
7 ; It implements a simple form of programmable turtle for VT100 compatible
8 ; terminals.
10 ; To run it:
12 ; A>xlisp turtles
14 ; This should cause the screen to be cleared and two turtles to appear.
15 ; They should each execute their simple programs and then the prompt
16 ; should return. Look at the code to see how all of this works.
18 ; Get some more memory
19 (expand 1)
21 ; delay a while
22 #+:times (defun pause (time)
23 (let ((fintime (+ (* time internal-time-units-per-second)
24 (get-internal-run-time))))
25 (loop (when (> (get-internal-run-time) fintime)
26 (return-from pause)))))
27 #-:times (defun pause () (dotimes (x (* time 1000))))
29 (defmacro delay () (pause 0.5))
32 ; Clear the screen
33 (defun clear ()
34 (princ "\033[H\033[2J"))
36 ; Move the cursor
37 (defun setpos (x y)
38 (princ "\033[") (princ y) (princ ";") (princ x) (princ "H"))
40 ; Kill the remainder of the line
41 (defun kill ()
42 (princ "\033[K"))
44 ; Move the cursor to the currently set bottom position and clear the line
45 ; under it
46 (defun bottom ()
47 (setpos *bx* (+ *by* 1))
48 (kill)
49 (setpos *bx* *by*)
50 (kill))
52 ; Clear the screen and go to the bottom
53 (defun cb ()
54 (clear)
55 (bottom))
58 ; ::::::::::::
59 ; :: Turtle ::
60 ; ::::::::::::
62 ; Define "Turtle" class
63 (defclass Turtle ((xpos (setq *newx* (+ *newx* 1))) (ypos 12) (char "*")))
65 ; Message ":display" prints its char at its current position
66 (defmethod Turtle :display ()
67 (setpos xpos ypos)
68 (princ char)
69 (bottom)
70 self)
72 ; When the character is set, we want to redisplay
73 (defmethod Turtle :set-char (c)
74 (setq char c)
75 (send self :display))
77 ; Message ":char" sets char to its arg and displays it
78 (defmethod Turtle :set-char (c)
79 (setq char c)
80 (send self :display))
82 ; Message ":goto" goes to a new place after clearing old one
83 (defmethod Turtle :goto (x y)
84 (setpos xpos ypos) (princ " ")
85 (setq xpos x)
86 (setq ypos y)
87 (send self :display))
89 ; Message ":up" moves up if not at top
90 (defmethod Turtle :up ()
91 (if (> ypos 0)
92 (send self :goto xpos (- ypos 1))
93 (bottom)))
95 ; Message ":down" moves down if not at bottom
96 (defmethod Turtle :down ()
97 (if (< ypos *by*)
98 (send self :goto xpos (+ ypos 1))
99 (bottom)))
101 ; Message ":right" moves right if not at right
102 (defmethod Turtle :right ()
103 (if (< xpos 80)
104 (send self :goto (+ xpos 1) ypos)
105 (bottom)))
107 ; Message ":left" moves left if not at left
108 (defmethod Turtle :left ()
109 (if (> xpos 0)
110 (send self :goto (- xpos 1) ypos)
111 (bottom)))
113 ; :::::::::::::::::::
114 ; :: Circular-List ::
115 ; :::::::::::::::::::
118 ; Define a class to represent a circular list
119 (defclass Circular-List (prog pc))
121 ; Replace :isnew with something more appropriate
122 (defmethod Circular-List :isnew (&optional list)
123 (setf prog list pc list)
124 self) ; return self
126 ; Method to get next item in list
127 (defmethod Circular-List :next ()
128 (when (null pc) (setq pc prog))
129 (prog1 (car pc) (setq pc (cdr pc))))
132 ; :::::::::::::
133 ; :: PTurtle ::
134 ; :::::::::::::
136 ; Define "PTurtle" programable turtle class
137 (defclass PTurtle (prog) () Turtle)
139 ; Message ":program" stores a program
140 (defmethod PTurtle :program (p)
141 (setf prog (send Circular-List :new p))
142 self)
144 ; Message ":step" executes a single program step
145 (defmethod PTurtle :step ()
146 (when prog (send self (send prog :next)))
147 (delay)
148 self)
150 ; Message ":step#" steps each turtle program n times
151 (defmethod PTurtle :step# (n)
152 (dotimes (x n) (send self :step))
153 self)
156 ; ::::::::::::::
157 ; :: PTurtles ::
158 ; ::::::::::::::
160 ; Define "PTurtles" class
161 (defclass PTurtles (Turtles))
163 ; Message ":make" makes a programable turtle and adds it to the collection
164 (defmethod PTurtles :make (x y &aux newturtle)
165 (setq newturtle (send PTurtle :new :xpos x :ypos y))
166 (setq Turtles (cons newturtle Turtles))
167 newturtle)
169 ; Message ":step" steps each turtle program once
170 (defmethod PTurtles :step ()
171 (mapcar #'(lambda (Turtle) (send Turtle :step)) Turtles)
172 self)
174 ; Message ":step#" steps each turtle program n times
175 (defmethod PTurtles :step# (n)
176 (dotimes (x n) (send self :step))
177 self)
180 ; Initialize things and start up
181 (defvar *bx* 0)
182 (defvar *by* 20)
183 (defvar *newx* 0)
185 ; Create some programmable turtles
186 (cb)
187 (definst PTurtles Turtles)
188 (setq t1 (send Turtles :make 40 10))
189 (setq t2 (send Turtles :make 41 10))
190 (send t1 :program '(:left :left :right :right :up :up :down :down))
191 (send t2 :program '(:right :right :down :down :left :left :up :up))
192 (send t1 :set-char "+")
193 (defun doit ()
194 (progn
195 (cb)
196 (send t1 :step# 8)
197 (send t2 :step# 8)
198 (send Turtles :step# 8)))
199 (doit)