# MUD playing around with doors and rooms
[
hear] (class door ((src room) (dest room))
              (method new (begin
                    (src add (self))
                    (dest add (self))))
              (method access-from (lambda ((current room))
                        (cond ((current == (src)) (dest))
                          ((current == (dest)) (src))
                          0)))
              (method is-present (lambda ((current room))
                       (cond ((current == (src)) (true))
                         ((current == (dest)) (true))
                         (false)))));

[hear] (class room ()
              (field content (container new))
              (method unknown (lambda (x) (content (x)))));

       # need to fix up containers to use object equality
[hear] (define object-element
         (lambda (n lst)
           (> (list-length
           (select-match (lambda (x) (x == (n))) (lst)))
              0)));

[hear] (class container ()
           (field contents (cell new (vector)))
           (method inventory (contents get))
           (method add (lambda (x)
                 (if (not (object-element (x) (contents get)))
                     (contents set (prepend (x) (contents get)))
                     (false)))));

[hear] (define hall (room new));

[hear] (define kitchen (room new));

[hear] (define door1 (door new (hall) (kitchen)));

[hear] ((first (hall inventory)) == (door1));

[hear] ((first (kitchen inventory)) == (door1));

[hear] (door1 access-from (hall) == (kitchen));

[hear] (not (door1 access-from (hall) == (hall)));

[hear] (door1 access-from (kitchen) == (hall));

[hear] (define lawn (room new));

[hear] (define stairs (room new));

[hear] (define bedroom (room new));

[hear] (define nowhere (room new));

[hear] (define door2 (door new (hall) (lawn)));

[hear] (define door3 (door new (hall) (stairs)));

[hear] (define door4 (door new (stairs) (bedroom)));

[hear] (class character ()
              (field location (cell new (nowhere)))
              (method set-room (lambda ((r room)) (location set (r))))
              (method get-room (location get))
              (method update 0));

[hear] (define find-max-helper
         (lambda (test max idx n lst)
           (if (> (list-length (lst)) 0)
           (if (> (test (head (lst))) (max))
               (find-max-helper (test) (test (head (lst))) (n) (+ (n) 1) (tail (lst)))
               (find-max-helper (test) (max) (idx) (+ (n) 1) (tail (lst))))
           (idx))));

[hear] (define find-max-idx
         (lambda (test lst)
           (find-max-helper (test) (test (head (lst))) 0 0 (lst))));

[hear] (define find-min-helper
         (lambda (test max idx n lst)
           (if (> (list-length (lst)) 0)
           (if (< (test (head (lst))) (max))
               (find-min-helper (test) (test (head (lst))) (n) (+ (n) 1) (tail (lst)))
               (find-min-helper (test) (max) (idx) (+ (n) 1) (tail (lst))))
           (idx))));

[hear] (define find-min-idx
         (lambda (test lst)
           (find-min-helper (test) (test (head (lst))) 0 0 (lst))));

[hear] (= 2 (find-max-idx (lambda (x) (x)) (vector 3 4 5 0)));

[hear] (= 1 (find-max-idx (lambda (x) (x)) (vector 3 5 4 0)));

[hear] (= 0 (find-max-idx (lambda (x) (x)) (vector 5 3 4 0)));

       # the robo class makes a character that patrols from room to room
[hear] (class robo ()
              (field super (character new))
              (field timestamp (cell new 0))
              (field timestamp-map (cell new (lambda (x) 0)))
              (method unknown (lambda (x) (super (x))))
              (method update
                  (let ((exits
                     (select-match (lambda (x) (instanceof door (x)))
                           (self location inventory))))
                (let ((timestamps
                   (map (lambda (x) (timestamp-map get (x)))
                        (exits))))
                  (let ((chosen-exit (list-ref
                              (exits)
                              (find-min-idx (lambda (x) (x))
                                    (timestamps))))
                    (current-tmap (timestamp-map get))
                    (current-t (timestamp get)))
                    (begin
                      (self location set (chosen-exit
                              access-from
                              (self location get)))
                      (timestamp-map set
                             (lambda ((d door))
                           (if (d == (chosen-exit))
                               (current-t)
                               (current-tmap (d)))))
                      (timestamp set (+ (timestamp get) 1))))))));

[hear] (define myrobo (robo new));

[hear] (myrobo set-room (stairs));

[hear] (define which-room
         (lambda ((rr robo))
           (find-max-idx
            (lambda ((r room)) (if (r == (rr get-room)) 1 0))
            (vector (hall) (kitchen) (stairs) (lawn) (bedroom)))));

[hear] (define sequencer
         (lambda (n current lst)
           (if (< (current) (n))
           (begin
             (myrobo update)
             (sequencer
              (n)
              (+ (current) 1)
              (append
               (which-room (myrobo))
               (lst))))
           (lst))));

       # here is a list of the first 30 rooms the robot character visits
       # 0=hall, 1=kitchen, 2=stairs, 3=lawn, 4=bedroom
[hear] (list= (sequencer 30 0 (vector)) (vector 4 2 0 3 0 1 0 2 4 2 0 3 0 1 0 2 4 2 0 3 0 1 0 2 4 2 0 3 0 1));

       # Now should start to introduce a language to talk about what is
       # going on in the simulated world, and start to move away from
       # detailed mechanism