(DEFINE-FILE-INFO READTABLE "XCL" PACKAGE "INTERLISP")
(FILECREATED "12-Aug-87 03:05:50" {PHYLUM}<SHRAGER>LISP>QIX.\;3 11097  

      |changes| |to:|  (VARS QIXCOMS)

      |previous| |date:| " 1-Aug-87 17:04:27" {PHYLUM}<SHRAGER>LISP>QIX.\;2)


; Copyright (c) 1987 by Xerox Corporation.  All rights reserved.

(PRETTYCOMPRINT QIXCOMS)

(RPAQQ QIXCOMS ((FNS QIX.GROW QIX.IDLE QIX.MOVE.POINT QIX.PLAY)
                (RECORDS QIX.POINT)
                (P (SETQ IDLE.FUNCTIONS (CONS '("5 Qix's" 'QIX.IDLE) IDLE.FUNCTIONS)))))
(DEFINEQ

(QIX.GROW
  (LAMBDA (WINDOW DONTDISMISS)                       (* \; "Edited  1-Aug-87 16:57 by JEFF.SHRAGER")
          
          (* * |This| |sets| |up| \a QIX |the| |specified| |window.|
          |The| |QIX's| |parameters| |are| |defined| |at| |random,| |but| |with| 
          |reasonable| |value| |ranges.| |The| |dismiss| |argument| |tell| |the| QIX 
          |whether| |to| DISMISS |every| |cycle| |or| |not.|
          B\e |careful.|)

    (PROG (P P2 (W (OR WINDOW (CREATEW)))
             L)
          (SETQ *STOP.QIXS* NIL)
          
          (* * P |and| P2 |define| \a QIX.)

          (SETQ P (|create| QIX.POINT
                         X ← (RAND 1 200)
                         Y ← (RAND 1 100)
                         VH ← (RAND 1 20)
                         VV ← (RAND 1 20)))
          (SETQ P2 (|create| QIX.POINT
                          X ← (RAND 1 200)
                          Y ← (RAND 1 100)
                          VH ← (RAND 1 20)
                          VV ← (RAND 1 20)))
          
          (* * L |is| |the| |tail| |list.| I\t |starts| |out| |full| |of| NIL\s |and| 
          |gets| |filled| |as| |the| QIX |moves.| I\t |is| |also| |inserted| |in| |it's| 
          |own| |mouth| |so| |that| |the| |whole| |thing| |wraps| |around.|)

          (SETQ L (APPEND (|for| X |from| 1 |to| (RAND 5 25)
                             |collect| (COPY '(A S D F)))
                         (LIST (LIST (|fetch| X P)
                                     (|fetch| Y P)
                                     (|fetch| X P2)
                                     (|fetch| Y P2)))))
          (RPLACD (LAST L)
                 L)
      LOOP
          (COND
             (*STOP.QIXS* (RPLACD L NIL)
                    (RETURN NIL)))
          
          (* * |Draw| |the| |QIX's| |head| |line.|)

          (MOVETO (|fetch| X P)
                 (|fetch| Y P)
                 W)
          (DRAWTO (|fetch| X P2)
                 (|fetch| Y P2)
                 1
                 'REPLACE W)
          
          (* * |Move| |the| |points| |according| |to| |their| X |and| Y |velocities.|)

          (QIX.MOVE.POINT P W)
          (QIX.MOVE.POINT P2 W)
          
          (* * |Take| \a |deep| |breath| |if| |the| |user| |asks| |you| |to.|
          |This| |slows| |things| |down.|)

          (OR DONTDISMISS (DISMISS))
          
          (* * |Delete| |the| |first| |object| |on| |the| |tail| |list.|)

          (COND
             ((EQ (CAAR L)
                  'A))
             (T (PROG ((OLD (CAR L)))
                      (MOVETO (CAR OLD)
                             (CADR OLD)
                             W)
                      (DRAWTO (CADDR OLD)
                             (CADDDR OLD)
                             1
                             'ERASE W))))
          
          (* * |Replace| |the| |current| |point| |with| |the| |new| |head,| |which| 
          |effectively| |adds| |it| |to| |the| |end| |of| |the| |list,| |since| |we| 
          |them| |immediately| |move| |to| |the| |next| |elt| |in| |this| |circular| 
          |list.|)

          (RPLACA (CAR L)
                 (|fetch| X P))
          (RPLACA (CDAR L)
                 (|fetch| Y P))
          (RPLACA (CDDAR L)
                 (|fetch| X P2))
          (RPLACA (CDDDAR L)
                 (|fetch| Y P2))
          (SETQ L (CDR L))
          (GO LOOP))))

(QIX.IDLE
  (LAMBDA (W)                                        (* \; "Edited  1-Aug-87 16:58 by JEFF.SHRAGER")
          
          (* * CLOBBER ANY OLD QIXS THAT WERE LEFT AROUND
          (WASTING SPACE) FROM BEFORE.)

    (AND (BOUNDP '*OLD-QIXS*)
         (FOR Q IN *OLD-QIXS* DO (RPLACD Q NIL)))
    (PROG (P P2 L QIXS)
          
          (* * P |and| P2 |define| \a QIX.)

          (SETQ QIXS (|for| I |from| 1 |to| 5
                        |collect| (PROGN (SETQ P (|create| QIX.POINT
                                                        X ← (RAND 1 200)
                                                        Y ← (RAND 1 100)
                                                        VH ← (RAND 1 20)
                                                        VV ← (RAND 1 20)))
                                         (SETQ P2 (|create| QIX.POINT
                                                         X ← (RAND 1 200)
                                                         Y ← (RAND 1 100)
                                                         VH ← (RAND 1 20)
                                                         VV ← (RAND 1 20)))
          
          (* * L |is| |the| |tail| |list.| I\t |starts| |out| |full| |of| NIL\s |and| 
          |gets| |filled| |as| |the| QIX |moves.| I\t |is| |also| |inserted| |in| |it's| 
          |own| |mouth| |so| |that| |the| |whole| |thing| |wraps| |around.|)

                                         (SETQ L
                                          (APPEND (|for| X |from| 1 |to| (RAND 5 25)
                                                     |collect| (COPY '(A S D F)))
                                                 (LIST (LIST (|fetch| X P)
                                                             (|fetch| Y P)
                                                             (|fetch| X P2)
                                                             (|fetch| Y P2)))))
                                         (RPLACD (LAST L)
                                                L)
                                         (LIST P P2 L))))
          (SETQ *OLD-QIXS* QIXS)
      LOOP
          (DISMISS)
          (|for| Q |in| QIXS |do| (SETQ P (CAR Q))
                                  (SETQ P2 (CADR Q))
                                  (SETQ L (CADDR Q)) 
          
          (* * |Draw| |the| |QIX's| |head| |line.|)

                                  (MOVETO (|fetch| X P)
                                         (|fetch| Y P)
                                         W)
                                  (DRAWTO (|fetch| X P2)
                                         (|fetch| Y P2)
                                         1
                                         'REPLACE W) 
          
          (* * |Move| |the| |points| |according| |to| |their| X |and| Y |velocities.|)

                                  (QIX.MOVE.POINT P W)
                                  (QIX.MOVE.POINT P2 W) 
          
          (* * |Delete| |the| |first| |object| |on| |the| |tail| |list.|)

                                  (COND
                                     ((EQ (CAAR L)
                                          'A))
                                     (T (PROG ((OLD (CAR L)))
                                              (MOVETO (CAR OLD)
                                                     (CADR OLD)
                                                     W)
                                              (DRAWTO (CADDR OLD)
                                                     (CADDDR OLD)
                                                     1
                                                     'ERASE W)))) 
          
          (* * |Replace| |the| |current| |point| |with| |the| |new| |head,| |which| 
          |effectively| |adds| |it| |to| |the| |end| |of| |the| |list,| |since| |we| THEN 
          |immediately| |move| |to| |the| |next| |elt| |in| |this| |circular| |list.|)

                                  (RPLACA (CAR L)
                                         (|fetch| X P))
                                  (RPLACA (CDAR L)
                                         (|fetch| Y P))
                                  (RPLACA (CDDAR L)
                                         (|fetch| X P2))
                                  (RPLACA (CDDDAR L)
                                         (|fetch| Y P2))
                                  (RPLACA (CDDR Q)
                                         (CDR L)))
          (GO LOOP))))

(QIX.MOVE.POINT
  (LAMBDA (P W)                                              (* |edited:| "16-May-85 00:39")
          
          (* * |This| |guy| |updates| |the| QIX |line| |endpoints| |according| |to| 
          |their| |velocities| |in| |the| X |and| Y |directions.|
          I\f |we| |hit| \a |wall,| |then| |simply| |negate| |the| |relevant| |velocity| 
          |vector.|)

    (PROG ((VV (|fetch| VV P))
           (VH (|fetch| VH P))
           (X (|fetch| X P))
           (Y (|fetch| Y P)))
          (PROG ((NEWX (IPLUS X VH))
                 (NEWY (IPLUS Y VV)))
                (COND
                   ((LESSP NEWY 0)
                    (SETQ NEWY 0)
                    (SETQ VV (ITIMES -1 VV)))
                   ((GREATERP NEWY (WINDOWPROP W 'HEIGHT))
                    (SETQ NEWY (WINDOWPROP W 'HEIGHT))
                    (SETQ VV (ITIMES -1 VV))))
                (COND
                   ((LESSP NEWX 0)
                    (SETQ NEWX 0)
                    (SETQ VH (ITIMES -1 VH)))
                   ((GREATERP NEWX (WINDOWPROP W 'WIDTH))
                    (SETQ NEWX (WINDOWPROP W 'WIDTH))
                    (SETQ VH (ITIMES -1 VH))))
                (|replace| Y P NEWY)
                (|replace| X P NEWX)
                (|replace| VV P VV)
                (|replace| VH P VH)))))

(QIX.PLAY
  (LAMBDA (N)                                                (* |Jeff.Shrager| " 8-Sep-85 14:01")
                                                             (* "Jeff Shrager" "24-May-84 22:17")
          
          (* |This| |takes| |over| |the| |screen| |and| |sets| |up| \a |number| |of| QIX 
          |on| |it.| I\t |also| |hangs| |itself| |at| |the| |end| |so| |that| |the| TTY 
          |window| |doesn't| |come| |to| |the| |surface.|)

    (PROG ((W (CREATEW '(0 0 1024 830) NIL 1)))
          (|for| X |from| 1 |to| N |do| (ADD.PROCESS (LIST 'QIX.GROW (KWOTE W))))
          (UNTILMOUSESTATE (AND LEFT RIGHT MIDDLE)))))
)
(DECLARE\: EVAL@COMPILE

(RECORD QIX.POINT (X Y VH VV))
)
(SETQ IDLE.FUNCTIONS (CONS '("5 Qix's" 'QIX.IDLE) IDLE.FUNCTIONS))
(PUTPROPS QIX COPYRIGHT ("Xerox Corporation" 1987))
(DECLARE\: DONTCOPY
  (FILEMAP (NIL (539 10893 (QIX.GROW 549 . 4105) (QIX.IDLE 4107 . 8821) (QIX.MOVE.POINT 8823 . 10205) (
QIX.PLAY 10207 . 10891)))))
STOP