blob: f4a94cb8bbd3499afeac88a2a2def1013ea580d5 (
plain) (
blame)
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
;; ADV.SCM
;; This file contains the definitions for the objects in the adventure
;; game and some utility procedures.
(define-class (place name)
(instance-vars
(directions-and-neighbors '())
(things '())
(people '())
(entry-procs '())
(exit-procs '()))
(method (type) 'place)
(method (neighbors) (map cdr directions-and-neighbors))
(method (exits) (map car directions-and-neighbors))
(method (look-in direction)
(let ((pair (assoc direction directions-and-neighbors)))
(if (not pair)
'() ;; nothing in that direction
(cdr pair)))) ;; return the place object
(method (appear new-thing)
(if (memq new-thing things)
(error "Thing already in this place" (list name new-thing)))
(set! things (cons new-thing things))
'appeared)
(method (enter new-person)
(if (memq new-person people)
(error "Person already in this place" (list name new-person)))
(set! people (cons new-person people))
(for-each (lambda (proc) (proc)) entry-procs)
'appeared)
(method (gone thing)
(if (not (memq thing things))
(error "Disappearing thing not here" (list name thing)))
(set! things (delete thing things))
'disappeared)
(method (exit person)
(for-each (lambda (proc) (proc)) exit-procs)
(if (not (memq person people))
(error "Disappearing person not here" (list name person)))
(set! people (delete person people))
'disappeared)
(method (new-neighbor direction neighbor)
(if (assoc direction directions-and-neighbors)
(error "Direction already assigned a neighbor" (list name direction)))
(set! directions-and-neighbors
(cons (cons direction neighbor) directions-and-neighbors))
'connected)
(method (add-entry-procedure proc)
(set! entry-procs (cons proc entry-procs)))
(method (add-exit-procedure proc)
(set! exit-procs (cons proc exit-procs)))
(method (remove-entry-procedure proc)
(set! entry-procs (delete proc entry-procs)))
(method (remove-exit-procedure proc)
(set! exit-procs (delete proc exit-procs)))
(method (clear-all-procs)
(set! exit-procs '())
(set! entry-procs '())
'cleared) )
(define-class (person name place)
(instance-vars
(possessions '())
(saying ""))
(initialize
(ask place 'enter self))
(method (type) 'person)
(method (look-around)
(map (lambda (obj) (ask obj 'name))
(filter (lambda (thing) (not (eq? thing self)))
(append (ask place 'things) (ask place 'people)))))
(method (take thing)
(cond ((not (thing? thing)) (error "Not a thing" thing))
((not (memq thing (ask place 'things)))
(error "Thing taken not at this place"
(list (ask place 'name) thing)))
((memq thing possessions) (error "You already have it!"))
(else
(announce-take name thing)
(set! possessions (cons thing possessions))
;; If somebody already has this object...
(for-each
(lambda (pers)
(if (and (not (eq? pers self)) ; ignore myself
(memq thing (ask pers 'possessions)))
(begin
(ask pers 'lose thing)
(have-fit pers))))
(ask place 'people))
(ask thing 'change-possessor self)
'taken)))
(method (lose thing)
(set! possessions (delete thing possessions))
(ask thing 'change-possessor 'no-one)
'lost)
(method (talk) (print saying))
(method (set-talk string) (set! saying string))
(method (exits) (ask place 'exits))
(method (notice person) (ask self 'talk))
(method (go direction)
(let ((new-place (ask place 'look-in direction)))
(cond ((null? new-place)
(error "Can't go" direction))
(else
(ask place 'exit self)
(announce-move name place new-place)
(for-each
(lambda (p)
(ask place 'gone p)
(ask new-place 'appear p))
possessions)
(set! place new-place)
(ask new-place 'enter self))))) )
(define thing
(let ()
(lambda (class-message)
(cond
((eq? class-message 'instantiate)
(lambda (name)
(let ((self '()) (possessor 'no-one))
(define (dispatch message)
(cond
((eq? message 'initialize)
(lambda (value-for-self)
(set! self value-for-self)))
((eq? message 'send-usual-to-parent)
(error "Can't use USUAL without a parent." 'thing))
((eq? message 'name) (lambda () name))
((eq? message 'possessor) (lambda () possessor))
((eq? message 'type) (lambda () 'thing))
((eq? message 'change-possessor)
(lambda (new-possessor)
(set! possessor new-possessor)))
(else (no-method 'thing))))
dispatch)))
(else (error "Bad message to class" class-message))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Implementation of thieves for part two
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define *foods* '(pizza potstickers coffee))
(define (edible? thing)
(member? (ask thing 'name) *foods*))
(define-class (thief name initial-place)
(parent (person name initial-place))
(instance-vars
(behavior 'steal))
(method (type) 'thief)
(method (notice person)
(if (eq? behavior 'run)
(ask self 'go (pick-random (ask (usual 'place) 'exits)))
(let ((food-things
(filter (lambda (thing)
(and (edible? thing)
(not (eq? (ask thing 'possessor) self))))
(ask (usual 'place) 'things))))
(if (not (null? food-things))
(begin
(ask self 'take (car food-things))
(set! behavior 'run)
(ask self 'notice person)) )))) )
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Utility procedures
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; this next procedure is useful for moving around
(define (move-loop who)
(newline)
(print (ask who 'exits))
(display "? > ")
(let ((dir (read)))
(if (equal? dir 'stop)
(newline)
(begin (ask who 'go dir)
(move-loop who)))))
;; One-way paths connect individual places.
(define (can-go from direction to)
(ask from 'new-neighbor direction to))
(define (announce-take name thing)
(newline)
(display name)
(display " took ")
(display (ask thing 'name))
(newline))
(define (announce-move name old-place new-place)
(newline)
(newline)
(display name)
(display " moved from ")
(display (ask old-place 'name))
(display " to ")
(display (ask new-place 'name))
(newline))
(define (have-fit p)
(newline)
(display "Yaaah! ")
(display (ask p 'name))
(display " is upset!")
(newline))
(define (pick-random set)
(nth (random (length set)) set))
(define (delete thing stuff)
(cond ((null? stuff) '())
((eq? thing (car stuff)) (cdr stuff))
(else (cons (car stuff) (delete thing (cdr stuff)))) ))
(define (person? obj)
(and (procedure? obj)
(member? (ask obj 'type) '(person police thief))))
(define (thing? obj)
(and (procedure? obj)
(eq? (ask obj 'type) 'thing)))
|