Digital Clock
-------------

We would like to write a program that simulates the display of a
digital clock. The display should look like this:

     00:00:00

The easiest way to think (in terms of objects) about this display, is
to consider each digit an LED element (object). The two columns in
between are irrelevant--they are just fixed decorations. Next step is
to decide which class to base LED objects on? This is obvious, on
rewinding counter class.

When we have decided that, we have to determine the range of valid
values for each LED. The minimum value for all is shown above--all
zeros. The maximum, considering 24 hour clock is this: `29:59:59' .
They come in three pairs, and for the time being(1), we can say that
the right-hand LED ranges from 0 to 9, and the left-hand from 0 to 5,
except ten-hour LED from 0 to 2.

Each LED object should act independently, but to create a working
clock object, they need some sort of glue. The glue, in this case
will be the information which object to call next, after each LED has
done its part of job. The LED, after it has incremented its counter,
and displayed its value, must call the next LED. There are two
posibilities for calling sequence. First, and most freequent is to
call the seconds LED. The other is (if the counter is at zero) to
call next LED on the left. This means that each LED must have two
inputs indicating the names of two possible objects to call.

The last bit of information needed, is display coordinates for each
object. We intend to use `setcursor' to fix LEDs, so this input will
be in the form of a list [xccor ycoor]. Now we are ready for
`led.class':

     to led.class :next :previous :cursor.pos [:roll 9]
     static [[digit [(object.maker "rewinding.counter.class 0 :roll)]]
             [up :next] [first :previous] [position :cursor.pos]]
     lambda :msg
     setcursor :position
     casec [
        [first bf :msg]
        [[increment]
         [type send "digit "inc]
         [wait 0]
         [if zero? send "digit "get [send "up "increment]]
         [wait 10]
         [send "first "increment]]
        [[type] [op "led.object]]
        [else [op delegate "base.object :msg]]]
     end

STATIC line is straightforward; we create a rewinding counter object
with the range from 0 to 9. `roll' is an optional variable. If not
given, it will default to 9.

In the body of object procedure(2), we first position the cursor. LED
objects responds to only one message--INCREMENT. Method INCREMENT
does the following:

     Increments its counter.

     Displays the counter using `type'. That's why we need the first `wait 0', to force line--buffer flush.

     If the count is at zero, it sends the message INCREMENT to the next object (up).

     If not, waits a little (`wait 10'), and sends the massage INCREMENT to the first object.

What is left to do, is to write the DIGITAL.CLOCK class, that will
create all necessary LED objects, and start the clock:

     to digital.clock.class :pos
     static [[x [first :pos]] [y [last :pos]]]
     static [[hr10 [(object.maker "led.class "sec1 "sec1 (list :x :y) 2)]]
             [hr1 [(object.maker "led.class "hr10 "sec1 (list :x+1 :y))]]
             [min10 [(object.maker "led.class "hr1 "sec1 (list :x+3 :y) 5)]]
             [min1 [(object.maker "led.class "min10 "sec1 (list :x+4 :y))]]
             [sec10 [(object.maker "led.class "min1 "sec1 (list :x+6 :y) 5)]]
             [sec1 [(object.maker "led.class "sec10 "sec1 (list :x+7 :y))]]]
     lambda :msg
     setcursor (list :x-1 :y) type "| 00:00:0  |
     casec [
        [first bf :msg]
        [[start] [send "sec1 "increment]]
        [[type] [op "digital.clock.object]]
        [else [ct] [op delegate "base.object :msg]]]
     end

We need two STATIC lines, one to create static variables X, and Y
(coordinates), and the second to define all six LED objects with
appropriate initial values. Two lines are a must, because the second
line is using values x, and y from the first.

The only message is START, which sends the `sec1' object message
INCREMENT.

Let's try our clock:

     define "clock (object.maker "digital.clock.class [30 15])
     pr send "clock "start

This will display the six LED elements, and start counting. The only
way to stop the clock, is to hit C-c C-c. We can delete the CLOCK
with `pr send "clock "erase.object'.

If you waited a very long time (hope you did not), you would have
noticed that our clock is not perfect. It will count all the way to
`29:59:59', before restarting at `00:00:00'. Now is the time to fix
this.

What we need is two different HR1 objects. One to count from 0 to 9,
and one from 0 to 3 (to reset at a value of `23:59:59'). This creates
a problem in the calling sequence. If objects are to be truly
independent, they should not be aware of the problem that `hr1'
object has. The `min10' object (the only one that is calling `hr1'),
should not know, and indeed, does not know which of the two versions
of `hr1' to call. The solution to this is to create one `hr1' object
with dual personality--actually consisting of two different objects.

     to hr.class :next :previous :cursor.pos :roll1 :roll2
     static [[digit1 [(object.maker "rewinding.counter.class 0 :roll1)]]
             [digit2 [(object.maker "rewinding.counter.class 0 :roll2)]]
             [hr.switch [(object.maker "rewinding.counter.class 0 1)]]]
     static [[digit [(object.maker "swap.pair.class "digit1 "digit2)]]
             [up :next] [first :previous] [position :cursor.pos]]
     lambda :msg
     setcursor :position
     casec [
        [first bf :msg]
        [[increment]
         [type send send "digit "get "inc]
         [wait 0]
         [ifelse zero? send send "digit "get "get
                 [ignore (and [zero? send "hr.switch "inc]
                              [send "digit "swap]
                              [equal? send "digit "get "digit2]
                              [send "hr.switch "inc])
                         send "up "increment]
                 [send "first "increment]]]
        [[type] [op "hr.object]]
        [else [op delegate "base.object :msg]]]
     end

The first STATIC line creates two objects, with different roll-over
limits, and switch object (a counter) that will aid in deciding which
of the two to use. The second STATIC line creates jet another object
(based on the `swap.pair.class', that will hold both HR1 objects
(DIGIT1, and DIGIT2).

The body of the HR.CLASS object has (compared to ordinary LED
objects) become complicated. First of all, to use HR object we need
`indirect addressing'. We cannot simply send message INC to the DIGIT
object, because this is only a pair class object, and does not know
how to INC anything. What we need to do, is to send message INC to
the object that is stored in the first part of the DIGIT object.

Tht's why the first line of the INCREMENT method uses nested SEND:

     [type send send "digit "get "inc]

It would be easier to understand if it was written with parentheses,
but they are not necessary.

     [type send (send "digit "get) "inc]

The inner SEND retrieves the object (in the beginning DIGIT1) from
the DIGIT object, and then sends this object the message INC.
Likewise, the ifelse line uses the same technique, to get the value
of the counter from DIGIT1 object. `and' is used here as a control
structure, that performs series of tests on the SWITCH object, and
DIGIT object, to decide whether to swap the DIGIT1, and DIGIT2
objects or not.

The digital clock class has to be adjusted as well:

     to digital.clock.class :pos
     static [[x [first :pos]] [y [last :pos]]]
     static [[hr10 [(object.maker "led.class "sec1 "sec1 (list :x :y) 2)]]
             [hr1 [(object.maker "hr.class "hr10 "sec1 (list :x+1 :y) 9 3)]]
             [min10 [(object.maker "led.class "hr1 "sec1 (list :x+3 :y) 5)]]
             [min1 [(object.maker "led.class "min10 "sec1 (list :x+4 :y))]]
             [sec10 [(object.maker "led.class "min1 "sec1 (list :x+6 :y) 5)]]
             [sec1 [(object.maker "led.class "sec10 "sec1 (list :x+7 :y))]]]
     lambda :msg
     setcursor (list :x-1 :y) type "| 00:00:0  |
     casec [
        [first bf :msg]
        [[start] [send "sec1 "increment]]
        [[type] [op "digital.clock.object]]
        [else [ct] [op delegate "base.object :msg]]]
     end

We can try it the same way as before:

     define "clock (object.maker "digital.clock.class [30 15])
     pr send "clock "start

This one will work properly, however, instead of making programming
with objects easier, this solution has made it more difficult. We can
try to fix this using differnt approach, but first let's fix the
obvious: indirect addressing problem.

exercises
.........

`a'
     Write a new definition of the HR.CLASS, that does not use nested
     `send'.

     Hint: use the procedure `indirect'.

`b'
     Replace the `and' control structure with `if'

Better strategy for solving the dual HR1 object problem would be to
use the circular, or double.end class as a storage for different
types of HR1 object. This way, we can completely avoid the
complicated logic of switching:

     to hr.class :next :previous :cursor.pos :roll1 :roll2
     static [[digit1 [(object.maker "rewinding.counter.class 0 :roll1)]]
             [digit2 [(object.maker "rewinding.counter.class 0 :roll2)]]]
     static [[digit [(object.maker "double.end.class
                                   [digit1 digit1 digit2])]]
             [up :next] [first :previous] [position :cursor.pos]]
     lambda :msg
     setcursor :position
     casec [
        [first bf :msg]
        [[increment]
         [type indirect "digit "inc]
         [wait 0]
         [ifelse zero? indirect "digit "get
                 [ignore send "digit "shift.left send "up "increment]
                 [send "first "increment]]]
        [[type] [op "hr.object]]
        [else [op delegate "base.object :msg]]]
     end

In the second STATIC line, we create the DIGIT object based on the
double.end class, and initialize it with the sequence of HR1 object
names [digit1 digit1 digit2]. This sequence has objects aligned in
the proper order. We use DIGIT1 (from 0 to 9) twice, then DIGIT2
(from 0 to 3) once. Whenever object's counter hits zero, we
SHIFT.LEFT the DIGIT object, therefore bringing the new HR1 object to
the front.

The sequence of DIGIT1/2 objects in the DIGIT object looks like this:

     [digit1 digit1 digit2]
     [digit1 digit2 digit1]
     [digit2 digit1 digit1]
     [digit1 digit1 digit2]
     ...

---------- Footnotes ----------

(1) The maximum value for hour LED is not always correct.

(2) Note that we use `casec' control structure, and not `case'. LED
object, does not return any values during its normal work, but values
do have to be returned anyway--at least for the TYPE message, and for
delegated messages (mostly ERASE.OBJECT). Therefore CASEC is used, as
it appends `output "#unspecified' to all true forms. For those TRUE
forms that actually do return values, you have to use explicit
`output'--as in TYPE, and DELEGATE.

Queens
------

This is a very popular problem, and has been used in many books to
explain backtracking. The functional(1) solution has already been
presented in this manual.See LOCAL PROCEDURES. Now, let's see if
we can make it simpler using objects.

Problem description: We have a chessboard, and eight queens. The
intention is to place all of queens onto the board in such a way,
that none of the queens is immediately threatening others.

This is usually solved placing queens one by one onto the board, on
the first available position (each in its own column), and performing
a check (before the queen is placed) whether it attacks any of the
previously placed queens. If it does not, it is placed on that
position. If it does, we try to place it on the next row (in the same
column). Sooner or later, we will not be able to find the position
for the next queen, which means that one (or more) of previously
placed queens will have to be picked up, and placed on the next
available row in their respective columns. This is the backtracking
part.

If you read the previous paragraph one more time, you will notice
words like; we try to place it, we will not be able to find the
position, previously placed queens will have to be picked up... It
sounds as if somebody is doing something with the queens, and queens
themselves are just decoration. This *we*, is actually a controlling
procedure (`put.queen' in this manual), that has the complete
overview of the chessboard, and all the queens.

In this section we will try a different approach. We will regard each
queen as an independent object, that knows what to do with itself.
That is all queens will know how to place themselves on the board,
and how to remove themselves from the board if need be. They will all
need to have access to the chessboard, for checking if the intended
next position is valid, and for inserting or removing themselves
on/from the board.

As with the digital clock, each queen will need some sort of glue.
This glue will be the knowledge which queen to call after the present
queen has successfully placed itself onto the board, and which queen
to call if this queen failed to find place for itself(2).

As you can see, there is no controlling procedure here--all queen
objects are of equal status. To be able to terminate the program, we
will use two border objects, one as the next object after the eighth
queen (which will indicate success, as all eight queens have been
placed), and one before the first queen (which will indicate total
failure, as the backtracking has been carried right off the board).

The queens will have to respond to two messages; PUT, and REMOVE.
That is, if one queen has placed itself successfully onto the board,
it will send the next queen message PUT, and if it failed, it will
send the previous queen the message REMOVE. The only private
information that each queen needs is the row of their current
position. As rows range from 1 to 8, it is obvious that the easiest
storage class to base the queen object is rewinding.counter.class .

The chessboard object will have to hold up to 8 numbers, representing
the columns that each queen occupies. Let's take a look at how queens
place themselves onto the board. If a queen needs to place itself, it
will push the number of its current column on the board, and then the
next will do the same thing, and the next ... If a queen needs to
remove itself, it will be always the last queen that has placed
itself, so we end up with a FIFO(3) structure. In LOOPS base classes
we have a ready made class for this; the STACK.CLASS.

Now, we are ready to define the `queen.class':

     to queen.class :prev.q [:next.q []]
     static [[column [(object.maker "rewinding.counter.class 0 8)]]
             [previous :prev.q] [next :next.q]]
     lambda :message
     local [self msg tmp]
     make "self first :message make "msg bf :message
     case [
        [first :msg]
        [[put]
         [make "tmp send "column "inc]
         [if zero? :tmp [op send "previous "remove]]
         [if (legal? send "board "get)
             [ignore (send "board "push :tmp) op send "next "put]]
         [op send "self "put]]
        [[remove]
         [ignore send "board "pop]
         [op send "self "put]]
        [[reset] [op send "column "reset]]
        [[type] [op "queen.object]]
        [else [op delegate "base.object :message]]]
     end

The STATIC line is very simple; we create the COLUMN, a rewinding
counter object that ranges from 0 to 8. One to eight being the
available rows in the designated queen's column, and 0 being the
signal, that the queen failed to find a place for itself.

The QUEEN OBJECT responds to these messages:

`put'
     Increments the column, and stores that number in TMP variable.
     If column is zero (failure), sends the previous queen the
     message REMOVE. If not, checks if the column number would be a
     legal position (with respect to the queens already placed). If
     true, pushes this number onto the stack (chessboard), and sends
     the message PUT to the next queen. If false, sends itself
     (object self) message PUT, which will repeat the same process.

`remove'
     Pops its current position from the stack (chessboard), and sends
     itself (object self) message PUT.

`reset'
     Resets the internal counter to 0

There is one novel concept here--the object SELF, used to carry out
recursive calls. The object SELF is just a local variable,
initialized every time the queen object is called, with the queen's
name. Remember that each call looks like this:
`send "queen.name "message'. This `queen.name' becomes the value of
variable SELF. This is one of the reasons we need the procedure
`send'. See SENDING MESSAGES.

The variable BOARD used in the queen object is the local variable
created in the `queens8.class', that we have to write next. Logo's
dynamic scope is used in queen object to access (and change) its
value.

QUEENS8 object will be the object responsible for creating all eight
queen objects, the chessboard object, and for starting the position
search process.

     to queens8.class
     static [[board [(object.maker "stack.class)]]
             [counter [(object.maker "counter.class 0)]]]
     static [[start.o [(object.maker "border.class
                                     [No further positions!] [self] [exit.outer])]]
             [end.o [(object.maker "border.class
                                   [Position] [counter board] [inc get])]]]
     static [[q1 [(object.maker "queen.class "start.o "q2)]]
             [q2 [(object.maker "queen.class "q1 "q3)]]
             [q3 [(object.maker "queen.class "q2 "q4)]]
             [q4 [(object.maker "queen.class "q3 "q5)]]
             [q5 [(object.maker "queen.class "q4 "q6)]]
             [q6 [(object.maker "queen.class "q5 "q7)]]
             [q7 [(object.maker "queen.class "q6 "q8)]]
             [q8 [(object.maker "queen.class "q7 "end.o)]]]
     lambda :msg
     case [
        [first bf :msg]
        [[next]
         [op ifelse send "board "empty? [send "q1 "put] [send "q8 "remove]]]
        [[reset]
         [foreach [q1 q2 q3 q4 q5 q6 q7 q8] [[q] [ignore send "q "reset]]]
         [ignore send "board "flush]
         [op send "counter "reset]]
        [[type] [op "queens8.object]]
        [else [op delegate "base.object :msg]]]
     end

The first STATIC line creates BOARD (stack), and a COUNTER objects.
The counter will count found positions (there are totally 92 for
eight queens). The second STATIC line will create two objects
(start.o, and end.o) of the border.class, whose purpose is to stop
the execution if the eighth queen managed to place itself (end.o), or
if the first queen tried to backtrack (start.o). The third STATIC
line creates the eight queen objects. Each queen is initialized with
its previous, and next queens. In case of Q1 previous is START.O, and
for Q8 next is END.O.

The order of static lines is unimportant--they could actually be
written as one line only. Note that queens  do not use as
initializing values objects themselves, but their names only. For the
queen to be initialized with the value of the object, that object had
to be created in one of the preceding STATIC lines. There is no way
to do this for queen objects, even if we use separate static line for
each queen. To create Q1, we need Q2, and to create Q2, we need Q1--a
dead end! Using names of objects (ordinary Logo words), on the other
hand is OK. That is why we have the procedure SEND, to dereference
the name until it gets to the object, but that happens during
run-time, when the object does exist, and not during compile-time.

The QUEENS8 OBJECT responds to following messages:

`next'
     If the board is empty (we are just starting) send Q1 the message
     PUT. If not, (this will not be the first position) send Q8 the
     message REMOVE. This will backtrack to find the next position.

`reset'
     Sends the message RESET to all the queens, flushes the board,
     and resets the position counter to 0.

It is obvious that the run-time part of QUEENS8 object is trivial,
however, one of its STATIC lines is not. We have not jet fully
explained the second line, one using the BORDER.CLASS. The END.O is
an instance of the BORDER.CLASS, and takes three initial values.
First is the text message [Position], which will be displayed when
the object is called. The second is a list of objects [counter
board], and the third, a list of messages [inc get]. What happens,
when the object END.O is invoked(4), is that it first types the text
from the first input, and then starts sending the objects from the
second list, the messages from the third. Obviously, number of
objects, and messages must match. The start object will be explained
later, when we write the driver procedure.

To test our queens, we need one more procedure, legal? :

     to legal? :plist [:up :tmp+1] [:down :tmp-1] 3
     if.tf emptyp :plist [op "true]
     if.tf memberp first :plist (list :tmp :up :down) [op "false]
     op legal? bf :plist :up+1 :down-1
     end

Note that the `legal?' contains free variable TMP. We are counting on
Logo's dynamic scope again. This does not have to be so, but since
the procedure `legal?' cannot be used by anything else but an queen
object, we let it go at that.

Now, we can test queens:

     define "queens (object.maker "queens8.class)

     pr send "queens "next
     Position 1 [4 2 7 3 6 8 5 1]
     pr send "queens "next
     Position 2 [5 2 4 7 3 8 6 1]
     pr send "queens "next
     Position 3 [3 5 2 8 6 4 7 1]
     pr send "queens "reset
     0
     pr send "queens "erase.object
     22707 127950

This will be very slow, more that ten times slower than the
functional solution.

If we want to automate finding of all solutions, we need a driver
procedure:

     to all.queens
     local "result
     if not definedp "queens8 [define "queens8 (object.maker "queens8.class)]
     while [make "result send "queens8 "next last :result] ~
           [pr :result]
     ignore send "queens8 "reset
     pr bl :result
     end

Now would be a good time to explain the START.O, from the second
static line. It is initialized with the text [No further positions!],
a list of objects [self], and a list of messages [exit.outer]. When
the START.O receives message REMOVE, from the Q1, that is trying to
backtrack, it will (first ignore the REMOVE message, and send itself
(object SELF) the message EXIT.OUTER, that will output `false'. This
`false' will be caught by `while' in the driver procedure, and will
exit the loop, displaying the text message; No further positions!.

     all.queens
     Position 1 [4 2 7 3 6 8 5 1]
     Position 2 [5 2 4 7 3 8 6 1]
     ...
     Position 90 [6 4 7 1 3 5 2 8]
     Position 91 [4 7 5 2 6 1 3 8]
     Position 92 [5 7 2 6 3 1 4 8]
     No further positions!

We have defined two global procedures for the queens program; legal?
and all.queens. It sounds logical to have the global driver
procedure, but let's examine the other. `legal?' is, and can be used
only by the queen objects, which are not global, but virtual objects.
It is obvious that `legal?' should become an local procedure.

LOOPS provides two ways to do this. One is obvious, and is mentioned
many times before; each queen can have its own local procedure
`legal?', defined using LETREC. However this would be a waste of
memory. So here is the other way. The QUEENS8.CLASS can define and
export a method LEGAL?. What this means is that `legal?' is defined
only once, but can be used by all the objects, it was exported to
(actually, all the classes).

     to queens8.class
     static [[board [(object.maker "stack.class)]]
             [counter [(object.maker "counter.class 0)]]
             [legal? [method.export [queen.class] [
                [plist [up :tmp + 1] [down :tmp - 1] 3]
                [if.tf emptyp :plist [op "true]]
                [if.tf memberp first :plist (list :tmp :up :down) [op "false]]
                [op (legal? bf :plist :up+1 :down-1)]]]]]
     static [[start.o [(object.maker "border.class
                                     [No further positions!] [self] [exit.outer])]]
             [end.o [(object.maker "border.class
                                   [Position] [counter board] [inc get])]]]
     static [[q1 [(object.maker "queen.class "start.o "q2)]]
             [q2 [(object.maker "queen.class "q1 "q3)]]
             [q3 [(object.maker "queen.class "q2 "q4)]]
             [q4 [(object.maker "queen.class "q3 "q5)]]
             [q5 [(object.maker "queen.class "q4 "q6)]]
             [q6 [(object.maker "queen.class "q5 "q7)]]
             [q7 [(object.maker "queen.class "q6 "q8)]]
             [q8 [(object.maker "queen.class "q7 "end.o)]]]
     lambda :msg
     case [
        [first bf :msg]
        [[next]
         [op ifelse send "board "empty? [send "q1 "put] [send "q8 "remove]]]
        [[reset]
         [foreach [q1 q2 q3 q4 q5 q6 q7 q8] [[q] [ignore send "q "reset]]]
         [ignore send "board "flush]
         [op send "counter "reset]]
         [[type] [op "queen8.object]]
        [else [op delegate "base.object :msg]]]
     end

Exported methods are defined inside the STATIC line, but have a
different syntax:

     static [method.name [method.export [list of classes to export to] [
            text of the procedure ...]]]

This looks similar to the `letrec' definition, but is preceded by the
keyword METHOD.EXPORT, and a list of classes the method will be
exported to. The invocation of the exported method LEGAL? requires
the same rules as the LETREC. Invocation must be enclosed in
parentheses. However the important difference is that if you define
several methods in one class, they cannot be mutually recursive.

There is no need to alter the QUEEN.CLASS to work with the method
LEGAL?, as the invocation was enclosed in parenthesis before. Method
LEGAL? can be used only in queen objects, as it is exported only to
the queen class.  Note that the LEGAL? in the form of exported
method, uses the dynamic scope, just like the global procedure.

Exercises
.........

Write the version of queen class that uses letrec instead of global
procedure, or exported method.

---------- Footnotes ----------

(1) It is not purely functional, because it uses the stack to store
all solutions.

(2) this is the backtracking part.

(3) First In First Out

(4) This happens when Q8 sends the message PUT to the next queen,
which is END.O

ANSWERS
*******

Round Table
-----------

;; a
     to round.table.class
     static [[circle [(object.maker "circular.class)]]]
     lambda :msg
     op case [
        [first bf :msg]
        [[last?] [(send "circle "count) = 1]]
        [[skip]
         [ignore (send "circle "sety  send "circle "first)]
         [ignore send "circle "rotate]
         [send "circle "gety]]
        [[execute output]
         [ignore (send "circle "sety  send "circle "first)]
         [ignore send "circle "bf]
         [send "circle "gety]]
        [[initialize]
         [(send "circle "import map "identity first bf bf :msg)]]
        [[type] ["knights.object]]
        [else [delegate "base.object :msg]]]
     end

;; b

The butfirst part of the START.O will be used for storing temporary
values. If you check the `circular.class' code, you will se that the
messages unknown to the circular class objects are delegated to the
START.O object. In our exercise, the unknown messages are SETY, and
GETY.

Clock
-----

;; a

     to hr.class :next :previous :cursor.pos :roll1 :roll2
     static [[digit1 [(object.maker "rewinding.counter.class 0 :roll1)]]
             [digit2 [(object.maker "rewinding.counter.class 0 :roll2)]]
             [hr.switch [(object.maker "rewinding.counter.class 0 1)]]]
     static [[digit [(object.maker "swap.pair.class "digit1 "digit2)]]
             [up :next] [first :previous] [position :cursor.pos]]
     lambda :msg
     setcursor :position
     casec [
        [first bf :msg]
        [[increment]
         [type indirect "digit "inc]
         [wait 0]
         [ifelse zero? indirect "digit "get
                 [ignore (and [zero? send "hr.switch "inc]
                              [send "digit "swap]
                              [equal? send "digit "get "digit2]
                              [send "hr.switch "inc])
                         send "up "increment]
                 [send "first "increment]]]
        [[type] [op "hr.object]]
        [else [op delegate "base.object :msg]]]
     end

;; b

     to hr.class :next :previous :cursor.pos :roll1 :roll2
     static [[digit1 [(object.maker "rewinding.counter.class 0 :roll1)]]
             [digit2 [(object.maker "rewinding.counter.class 0 :roll2)]]
             [hr.switch [(object.maker "rewinding.counter.class 0 1)]]]
     static [[digit [(object.maker "swap.pair.class "digit1 "digit2)]]
             [up :next] [first :previous] [position :cursor.pos]]
     lambda :msg
     setcursor :position
     casec [
        [first bf :msg]
        [[increment]
         [type indirect "digit "inc]
         [wait 0]
         [ifelse zero? indirect "digit "get
                 [if (or [equal? send "digit "get "digit2]
                         [zero? send "hr.switch "inc])
                     [ignore send "digit "swap]
                     send "up "increment]
                 [send "first "increment]]]
        [[type] [op "digital.clock.object]]
        [else [op delegate "base.object :msg]]]
     end

Queeens
-------

     to queen.class :prev.q [:next.q []]
     static [[column [(object.maker "rewinding.counter.class 0 8)]]
             [previous :prev.q] [next :next.q]]
     lambda :message
     local [self msg tmp]
     make "self first :message make "msg bf :message
     op letrec [[
        [legal? [[plist [up :tmp + 1] [down :tmp - 1] 3]
                 [if.tf emptyp :plist [op "true]]
                 [if.tf memberp first :plist (list :tmp :up :down) [op "false]]
                 [op (legal? bf :plist :up+1 :down-1)]]]]
                [case [
                   [first :msg]
                   [[put]
                    [make "tmp send "column "inc]
                    [if zero? :tmp [op send "previous "remove]]
                    [if (legal? send "board "get)
                        [ignore (send "board "push :tmp) op send "next "put]]
                    [op send "self "put]]
                   [[remove]
                    [ignore send "board "pop]
                    [op send "self "put]]
                   [[reset] [op send "column "reset]]
                   [[type] [op "queen.object]]
                   [else [delegate "base.object :message]]]]]
     end