From @life.ai.mit.edu:antkam@athena.mit.edu Wed Nov  6 17:55:34 1991
Received: by hx.LCS.MIT.EDU (5.51/4.7); Wed, 6 Nov 91 17:55:31 EST
Received: from life.ai.mit.edu by mintaka.lcs.mit.edu id aa02011;
          6 Nov 91 17:53 EST
Received: from Athena.MIT.EDU by life.ai.mit.edu (4.1/AI-4.10) id AA11324; Wed, 6 Nov 91 17:53:08 EST
Received: from GARDNER-R-DOZOIS.MIT.EDU by Athena.MIT.EDU with SMTP
	id AA04729; Wed, 6 Nov 91 17:53:05 EST
From: antkam@athena.mit.edu
Received: by gardner-r-dozois.MIT.EDU (5.61/4.7) id AA12919; Wed, 6 Nov 91 17:53:01 -0500
Message-Id: <9111062253.AA12919@gardner-r-dozois.MIT.EDU>
To: ziggy@ai.mit.edu, antkam@athena.mit.edu
Subject: ps6 pseudo-bug report
Date: Wed, 06 Nov 91 17:52:58 EST
Status: R


hi ziggy, 

this is neither urgent nor very important, and i just want to send to
you for record.  i am not sure this is worth staff list discussion.

antkam

---

the way we implemented (clock), it would cdr down the *clock-list*
asking each person to act.  however, the *clock-list* it cdr's down is
the one just before the tick.  so, if some person p is
removed-from-clock-list during a tick, the for-each inside (clock) will
not see the change in *clock-list*.  (because remove-from-clock-list is
implemented using (set! *clock-list* (delq ...)) and so for-each, having
already grabbed its argument, will not see its argument changed.)
hence, if p hasnt acted yet in that tick, p will be asked to act when
for-each cdr's down to p.

this is not a bug as of now, because if a person is asked to act in
heaven, he will not do anything.  (because heaven is not connected to
anywhere so a person has nothing to do.)  however, if there are two
trolls, each active at the same tick, the first one eats the second one,
then when the second one is asked to act it may eat somebody in heaven.
that would be a "bug".  (i said "bug" because the PS never really
specified this case, so in theory any behavior is acceptable.)

the following is a simpler example...

-----------------------------------------

(define (make-actor name place)
  (let ((p (make-person name place 1)))		; threshold = 1
    (lambda (message)
      (cond ((eq? message 'act) 
	     (lambda (self) (ask self 'say '(i am acting!))))	; always act
	    (else (get-method p message))))))
;Value: make-actor

(define (make&install-actor name place)
  (let ((a (make-actor name place)))
    (ask a 'install)
    a))
;Value: make&install-actor

--- "correct" behavior ---

(initialize-clock-list)
;Value: initialized

(define room (make-place 'room))
;Value: room

(define silly (make&install-troll 'silly room 1))
;Value: silly

(define stupid (make&install-actor 'stupid room))
;Value: stupid

(define heaven (make-place 'heaven))
;Value: heaven

(mapcar (lambda (p) (ask p 'name)) *clock-list*)
;Value: (stupid silly)		; stupid-the-actor will be asked to act
				; first since for-each cdr's down the list

(run-clock 2)
---Tick---
---Tick---
At room : stupid says -- i am acting! 			; stupid acts first

At room : silly says -- Growl.... I'm going to eat you, stupid 	; silly acts
At room : stupid says -- 					; and eats
                   Do what you will, to your hurt and shame, 	; stupid
                   but none of my programs, in God's name,
                   shall you touch. 
stupid moves from room to heaven 
At room : silly says -- Chomp chomp. stupid tastes yummy! 

;Value: done

--- "buggy" behavior ---

(initialize-clock-list)
;Value: initialized

(define room2 (make-place 'room2))
;Value: room2

(define lucky (make&install-actor 'lucky room2))
;Value: lucky

(define happy (make&install-troll 'happy room2 1))
;Value: happy

(define heaven (make-place 'heaven))
;Value: heaven

(mapcar (lambda (p) (ask p 'name)) *clock-list*)
;Value: (happy lucky)		; happy-the-troll will be asked to act
				; first since for-each cdr's down the list

(run-clock 2)
---Tick---
---Tick---

At room2 : happy says -- Growl.... I'm going to eat you, lucky 	; happy acts
At room2 : lucky says -- 					; and eats
                   Do what you will, to your hurt and shame, 	; lucky, who
                   but none of my programs, in God's name,	; dies and
                   shall you touch. 				; is removed
lucky moves from room2 to heaven 				; from 
At room2 : happy says -- Chomp chomp. lucky tastes yummy! 	; *clock-list*

At heaven : lucky says -- i am acting! 		; lucky, dead and not on
						; *clock-list*, still acts!
;Value: done

------------------------------------------

note that the only difference between the "correct" and "buggy" version
is the order in which the troll and the actor are installed onto
*clock-list*.  this, IMHO, is quite undesirable.  

one simple fix is not to use set! and delq in remove-from-clock-list.
instead, use set-car! and set-cdr! to surgically remove the dead person
from the list.  then even the for-each inside (clock) will see the
difference.  add-to-clock-list doesnt have to be changed because the guy
cons'ed onto *clock-list* will not be seen by the for-each inside
(clock), which is ok.  (i.e. a person does not act during the tick it is
first created.)

-----------------------------------------

that's all for now!

antkam

p.s.: i discovered this "bug" while looking at my student joe b.'s
transcript.

