Define a method
take-all for people. If given that message, a person should
take all the things at the current location that are not already owned by
> (ask someperson 'take-all)
It's unrealistic that anyone can take anything from anyone. We want to give
our characters a
strength, and then one person can take something from
another only if the first has greater
strength than the second.
However, we aren't going to clutter up the person class by adding a local
strength variable. That's because we can anticipate wanting to add lots more
attributes as we develop the program further. People can have charisma or
wisdom; things can be food or not; places can be indoors or not.
Therefore, you will create a class called
basic-object that keeps a local
properties containing an attribute-value table like the one
that we used with
put in Lesson 6. However,
refer to a single, fixed table for all operations; in this situation we need a
separate table for every object. The file
tables.scm contains an
implementation of the table Abstract Data Type:
(make-table)returns a new, empty table.
(insert! key value table)adds a new key-value pair to a table.
(lookup key table)returns the corresponding value, or
#fif 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.
You'll modify the
thing classes so that they will inherit from
basic-object. This object will accept a message
put so that the following call does the right thing:
> (ask Brian 'put 'strength 100)
basic-object should treat any message not otherwise recognized as a request for the attribute of that name, so
> (ask Brian 'strength) 100
should work WITHOUT having to write an explicit
strength method in the class
Don't forget that the property list mechanism returns
#f if you ask for a property that isn't in the list. This means that the following call should never give an error message, even if we haven't
put that property in that object:
> (ask Brian 'charisma)
This is important for true-or-false properties, which will automatically be
#f (but not an error) unless we explicitly
#t value for them.
Give people some reasonable initial strength. (They should be the same for every newly instantiated person object.) Later, they'll be able to get stronger by eating.
You'll notice that the type predicate
person? checks to see if the type of
the argument is a member of the list
'(person police thief). This means that
person? procedure has to keep a list of all the classes that inherit
person, which is a pain if we make a new subclass.
We'll take advantage of the property list to implement a better system for
type checking. If we add a method named
person? to the person class, and
have it always return
#t, then any object that's a type of person will
automatically inherit this method. Objects that don't inherit from person
won't find a
person? method and won't find an entry for
person? in their
property table, so they'll return
Similarly, places should have a
place? method, and things a
> (ask brian 'person?) #t
Add these type methods and change the implementation of the type predicate
procedures (at the very bottom of
adv.scm) to this new implementation. Don't
forget to add the definition for
The new type predicate should do the following:
> (person? brian) #t > (place? soda) #t > (thing? coffee) #t
person? should work for classes that inherit from
police (defined later). Similarly with
In the modern era, many places allow you to get connected to the net. Define a
hotspot as a kind of place that allows network connectivity. Each hotspot
should have a
name and a
password as instantiation variables that you must
know to connect.
> (define library (instantiate hotspot 'library 1234)) ;name of hotspot is library, password is 1234
(Note: We're envisioning a per-network password, not a per-person password as
you use with AirBears.) The hotspot has a
connect method with two arguments,
laptop (a kind of thing, to be invented in a moment) and a password. If
the password is correct, and the laptop is in the hotspot, add it to a list of
connected laptops otherwise, return an error. When the laptop leaves the
hotspot, remove it from the list.
> (ask library 'connect somelaptop 1234)
Hotspots also have a
surf method with two arguments, a laptop and a text
string, such as
If the laptop is connected to the network, then the surf method should
(system (string-append "lynx " url))
where URL is the text string argument (note the space after x in "lynx "). Otherwise, return an error.
> (ask library 'surf somelaptop "http://www.cs.berkeley.edu")
Now invent the
laptop class. A laptop has one instantiation variable, its
> (define somelaptop (instantiate laptop 'somelaptop)
A laptop is a thing that has two extra methods:
connect, with a password as
argument, sends a
connect message to the place where the laptop is. If the
password is wrong, return an error.
> (ask somelaptop 'connect 1234)
A laptop also has another method,
surf, with a URL text string as argument,
surf message to the place where it is. Thus, whenever a laptop
enters a new hotspot, the user must ask to
connect to that hotspot's
network; when the laptop leaves the hotspot, it must automatically be
disconnected from the network. (If it's in a place other than a hotspot, the
surf message won't be understood; if it's in a hotspot but not connected,
return an error).
> (ask somelaptop 'surf "www.berkeley.edu")