(FILECREATED " 8-Sep-85 14:02:40" {ERIS}<LISPUSERS>QIX.;3 4995   

      changes to:  (FNS QIX.PLAY QIX.GROW QIX.MOVE.POINT)

      previous date: "12-Feb-85 09:28:37" {ERIS}<LISPUSERS>QIX.;2)


(* Copyright (c) 1985 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT QIXCOMS)

(RPAQQ QIXCOMS ((FNS QIX.GROW QIX.MOVE.POINT QIX.PLAY)
		(RECORDS QIX.POINT)))
(DEFINEQ

(QIX.GROW
  [LAMBDA (WINDOW DONTDISMISS)                               (* Jeff.Shrager " 8-Sep-85 13:55")

          (* * 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. Be 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. It starts out full of NILs and gets filled as the QIX moves. It 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 (QUOTE (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
		  (QUOTE 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)
		 (QUOTE A)))
	    (T (PROG ((OLD (CAR L)))
		     (MOVETO (CAR OLD)
			     (CADR OLD)
			     W)
		     (DRAWTO (CADDR OLD)
			     (CADDDR OLD)
			     1
			     (QUOTE 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.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.
	  If 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 (QUOTE HEIGHT)))
		    (SETQ NEWY (WINDOWPROP W (QUOTE HEIGHT)))
		    (SETQ VV (ITIMES -1 VV]
	        [COND
		  ((LESSP NEWX 0)
		    (SETQ NEWX 0)
		    (SETQ VH (ITIMES -1 VH)))
		  ((GREATERP NEWX (WINDOWPROP W (QUOTE WIDTH)))
		    (SETQ NEWX (WINDOWPROP W (QUOTE 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. It also hangs itself at the end so that the TTY 
	  window doesn't come to the surface.)


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

(RECORD QIX.POINT (X Y VH VV))
]
(PUTPROPS QIX COPYRIGHT ("Xerox Corporation" 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (377 4859 (QIX.GROW 387 . 3058) (QIX.MOVE.POINT 3060 . 4214) (QIX.PLAY 4216 . 4857)))))
STOP