You will notice that whenever a person goes to a new place, the place gets an
'enter
message. In addition, the place the person previously inhabited gets
an 'exit
message. When the place gets the message, it calls each procedure
on its list of entry-procedures
or exit-procedures
as appropriate. Places
have the following methods defined for manipulating these lists of procedures:
add-entry-procedure
, add-exit-procedure
, remove-entry-procedure
, remove-exit-procedure
, and clear-all-procs
. You can read their definitions in the code.
Sproul Hall has a particularly obnoxious exit procedure attached to it. Fix
sproul-hall-exit
so that it counts how many times it gets called, and stops
being obnoxious after the third time.
Remember that the exit-procs
list contains procedures, not names of
procedures! It's not good enough to redefine sproul-hall-exit
, since Sproul
Hall's list of exit procedures still contains the old procedure. The best
thing to do is just to load adv-world.scm
again, which will define a new
Sproul Hall and add the new exit procedure.
We've provided people with the ability to say something using the messages
'talk
and 'set-talk
. As you may have noticed, some people around this
campus start talking whenever anyone walks by. We want to simulate this
behavior. In any such interaction there are two people involved: the one who
was already at the place (hereafter called the talker
) and the one who is
just entering the place (the listener
). We have already provided a mechanism
so that the listener
sends an enter
message to the place when entering.
Also, each person is ready to accept a notice
message, meaning that the
person should notice that someone new has come. The talker
should get a
notice
message, and will then talk, because we've made a person's notice
method send itself a talk
message. (Later we'll see that some special kinds
of people have different notice
methods.)
Your job is to modify the enter
method for places, so that in addition to
what that method already does, it sends a notice
message to each person in
that place other than the person who is entering. The notice
message
should have the newly-entered person as an argument. (You won't do anything
with that argument now, but you'll need it later.)
Add the following to adv-world.scm
:
(define singer (instantiate person 'rick sproul-plaza))
(ask singer 'set-talk "My funny valentine, sweet comic valentine")
(define preacher (instantiate person 'preacher sproul-plaza))
(ask preacher 'set-talk "Praise the Lord")
(define street-person (instantiate person 'harry telegraph-ave))
(ask street-person 'set-talk "Brother, can you spare a buck")
Try walking around to sproul-plaza
and telegraph-ave
to see if the messages are triggered.
You must include a transcript in which your character walks around and triggers these messages.
So far the program assumes that anyone can go anywhere they want. In real life, many places have locked doors.
Invent a may-enter?
message for places that takes a person as an argument
and always returns #t
. Then invent a locked-place
class in which the may-
enter?
method returns #t if the place is unlocked, or #f if it's locked. (It
should initially be locked.) The locked-place
class must also have an
unlock
message. For simplicity, write this method with no arguments and have
it always succeed. In a real game, we would also invent keys, and a mechanism
requiring that the person have the correct key in order to unlock the door.
(That's why may-enter?
takes the person as an argument.)
Modify the person
class so that it checks for permission to enter before
moving from one place to another. If a person cannot enter, return an error.
Then create a locked place and test it out.
Note: A locked-place should take one instantiation variable, its name.
(define warehouse (instantiate locked-place 'warehouse))
Walking around is great, but some people commute from far away, so they need
to park their vehicles in garages. A vehicle is just a thing
, but you'll
have to invent a special kind of place called a garage
. Garages have two
methods (besides the ones all places have): park
and unpark
. You'll also
need a special kind of thing
called a ticket
; what's special about it is
that it has a number
as an instantiation variable.
The park
method takes a vehicle (a thing
) as its argument. First check to
be sure that the vehicle is actually in the garage. (The person who possesses
the vehicle will enter the garage, then ask to park it, so the vehicle should
have entered the garage along with the person before the park
message is
sent.) Then generate a ticket
with a unique serial number. (The counter for
serial numbers should be shared among all garages, so that we don't get in
trouble later trying to unpark
a vehicle from one garage that was parked in
a different garage.) Every ticket should have the name ticket
.
You'll associate the ticket number with the vehicle in a key-value table like
the one that we used with get
and put
in Lesson 6. However, get
and put
refer to a single, fixed table for all operations; in this situation we need a
separate table for every garage. The file tables.scm
contains an
implementation of the table Abstract Data Type:
constructor: (make-table) returns a new, empty table.
mutator: (insert! key value table) adds a new key-value pair to a table.
selector: (lookup key table) returns the corresponding value, or #f if
the key is not in the table.
You'll learn how tables are implemented in SICP 3.3.3 (pp. 266-268). For now, just take them as primitive.
Make a table entry with the ticket number as the key, and the vehicle as the value. Then ask the vehicle's owner to lose the vehicle and take the ticket.
The unpark
method takes a ticket as argument. First make sure the object you
got is actually a ticket (by checking the name). Then look up the ticket
number in the garage's table. If you find a vehicle, ask the ticket's owner to
lose the ticket and take the vehicle. Also, insert #f
in the table for that
ticket number, so that people can't unpark the vehicle twice.
A real-life garage would have a limited capacity, and would charge money for parking, but to simplify the project you don't have to simulate those aspects of garages.
Be sure not to name anything a "car"! This will mess up everything!
Notes:
(instantiate ticket 120)
).'ticket
(instantiate garage 'soda-garage)
).