updated version, but need to update installation scripts
[cls.git] / xlisponly / lsp / blocks.lsp
blob8d6f9241910cd7d9fb834ccafba9a32c9dfa2ffb
1 ; Blocks World from Winston&Horn
3 #-:classes (load "classes")
5 ; abstract classes for ball types
7 ; basic blocks support nothing
8 (defclass basic-block (name width height position supported-by))
10 (defmethod basic-block :support-for () nil)
12 (defmethod basic-block :top-location ()
13 (list (+ (first position) (/ width 2))
14 (+ (second position) height)))
16 ; movable-blocks can be moved
17 (defclass movable-block () () basic-block)
19 ; load-bearing blocks can support other blocks, and can be moved
20 (defclass load-bearing-block (support-for) () movable-block)
22 ; we can't have multiple inheritance, so we need a separate class for table
23 ; table blocks can support other blocks but cannot be moved.
25 (defclass table-block (support-for) () basic-block)
27 ; Specific classes for table brick wedge and ball
29 (defclass brick () () load-bearing-block)
31 (defclass wedge () () movable-block)
33 (defclass ball () () movable-block)
35 (defclass hand (name position grasping))
38 ; define all the individual blocks
40 (setf *blocks*
41 (list
42 (send table-block :new :name 'table :width 20 :height 0 :position '(0 0))
43 (send brick :new :name 'b1 :width 2 :height 2 :position '(0 0))
44 (send brick :new :name 'b2 :width 2 :height 2 :position '(2 0))
45 (send brick :new :name 'b3 :width 4 :height 4 :position '(4 0))
46 (send brick :new :name 'b4 :width 2 :height 2 :position '(8 0))
47 (send wedge :new :name 'w5 :width 2 :height 4 :position '(10 0))
48 (send brick :new :name 'b6 :width 4 :height 2 :position '(12 0))
49 (send wedge :new :name 'w7 :width 2 :height 2 :position '(16 0))
50 (send ball :new :name 'l8 :width 2 :height 2 :position '(18 0))
53 (dolist (l *blocks*) (set (send l :name) l))
56 (dolist (l (cdr *blocks*)) ; all but table block
57 (setf (send table :support-for)
58 (cons l (send table :support-for))
59 (send l :supported-by)
60 table))
62 (definst hand *hand* :name '*hand* :position '(0 6))
64 (defmethod movable-block :put-on (support)
65 (if (send self :get-space support)
66 (and (send *hand* :grasp self)
67 (send *hand* :move self support)
68 (send *hand* :ungrasp self))
69 (format t
70 "Sorry, there is no room for ~a on ~a.~%"
71 name
72 (send support :name))))
74 (defmethod movable-block :get-space (support)
75 (or (send self :find-space support)
76 (send self :make-space support)))
78 (defmethod hand :grasp (obj)
79 (unless (eq grasping obj)
80 (when (send obj :support-for)
81 (send obj :clear-top))
82 (when grasping
83 (send grasping :rid-of))
84 (setf position (send obj :top-location))
85 (format t
86 "Move hand to pick up ~a at location ~a.~%"
87 (send obj :name)
88 position)
89 (format t
90 "Grasp ~a.~%"
91 (send obj :name))
92 (setf grasping obj))
95 (defmethod hand :ungrasp (obj)
96 (when (send obj :supported-by)
97 (format t
98 "Ungrasp ~a~%"
99 (send obj :name))
100 (setf grasping nil)
103 (defmethod movable-block :rid-of ()
104 (send self :put-on table))
106 (defmethod movable-block :make-space (support)
107 (dolist (obstruction (send support :support-for))
108 (send obstruction :rid-of)
109 (let ((space (send self :find-space support)))
110 (when space (return space)))))
112 (defmethod load-bearing-block :clear-top ()
113 (dolist (obstacle support-for) (send obstacle :rid-of))
117 (defmethod hand :move (obj support)
118 (send obj :remove-support)
119 (let ((newplace (send obj :get-space support)))
120 (format t
121 "Move ~a to top of ~a at location ~a.~%"
122 (send obj :name)
123 (send support :name)
124 newplace)
125 (setf (send obj :position) newplace)
126 (setf position (send obj :top-location)))
127 (send support :add-support obj)
131 ; remove-support-for is defined twice, for each load bearing class
133 (defmethod load-bearing-block :remove-support-for (obj)
134 (setf support-for (remove obj support-for))
137 (defmethod table-block :remove-support-for (obj)
138 (setf support-for (remove obj support-for))
141 (defmethod movable-block :remove-support ()
142 (when supported-by
143 (format t
144 "Removing support relations between ~a and ~a.~%"
145 (send supported-by :name)
146 name)
147 (send supported-by :remove-support-for self)
148 (setf supported-by nil))
151 (defmethod load-bearing-block :add-support (obj)
152 (format t
153 "Adding support relations between ~a and ~a.~%"
154 (send obj :name)
155 name)
156 (setf support-for
157 (cons obj support-for)
158 (send obj :supported-by)
159 self)
162 (defmethod table-block :add-support (obj)
163 (format t
164 "Adding support relations between ~a and ~a.~%"
165 (send obj :name)
166 name)
167 (setf support-for
168 (cons obj support-for)
169 (send obj :supported-by)
170 self)
173 (defmethod basic-block :add-support (obj)
176 (defmethod movable-block :find-space (support)
177 (dotimes (offset (1+ (- (send support :width) width)))
178 (unless (intersections-p self offset
179 (first (send support :position))
180 (send support :support-for))
181 (return (list (+ offset (first (send support
182 :position)))
183 (+ (second (send support :position))
184 (send support :height)))))))
186 (defun intersections-p (obj offset base obstacles)
187 (dolist (obstacle obstacles)
188 (let* ((ls-proposed (+ offset base))
189 (rs-proposed (+ ls-proposed (send obj :width)))
190 (ls-obstacle (first (send obstacle :position)))
191 (rs-obstacle (+ ls-obstacle (send obstacle :width))))
192 (unless (or (>= ls-proposed rs-obstacle)
193 (<= rs-proposed ls-obstacle))
194 (return t)))))