;;; -*- Mode:LISP; Package:USER; Readtable:CL; Base:10 -*-

(defun wow ()
  (dotimes (i 350)
    (send tv:initial-lisp-listener :draw-circle 400 400 (* 2 i)))
  (loop))

(defvar *window* tv:initial-lisp-listener)

(defconstant *square-root-of-two* (sqrt 2))

(defconstant *square-root-of-two-over-two* (/ 1 (sqrt 2)))

(defconstant *pi-over-four* (/ pi 4))

(defconstant *45-degree-left-rotation* 
	     (complex *square-root-of-two-over-two* *square-root-of-two-over-two*))

(defconstant *45-degree-right-rotation* 
	     (complex *square-root-of-two-over-two* (- *square-root-of-two-over-two*)))

(defvar *x* 0)

(defvar *y* 0)

(defun c-curve (length angle min-length)
  (if (< length min-length)
      (plot-line length angle)
      (progn
	(c-curve (* length *square-root-of-two-over-two*)
		 (+ angle *pi-over-four*)
		 min-length)
	(c-curve (* length *square-root-of-two-over-two*)
		 (- angle *pi-over-four*)
		 min-length))))

(defun dragon-curve (length angle min-length handedness)
  "See p. 348, 'LISP'."
  (if (< length min-length)
      (plot-line length angle)
      (progn
	(dragon-curve (* length *square-root-of-two-over-two*)
		      (+ angle (* handedness *pi-over-four*))
		      min-length
		      +1)
	(dragon-curve (* length *square-root-of-two-over-two*)
		      (- angle (* handedness *pi-over-four*))
		      min-length
		      -1))))

(defun turtle-depth-dragon-curve (length angle depth handedness)
  "See p. 348, 'LISP'."
  (if (zerop depth)
      (plot-line length angle)
      (progn
	(turtle-depth-dragon-curve (* length *square-root-of-two-over-two*)
			    (+ angle (* handedness *pi-over-four*))
			    (1- depth)
			    +1)
	(turtle-depth-dragon-curve (* length *square-root-of-two-over-two*)
			    (- angle (* handedness *pi-over-four*))
			    (1- depth)
			    -1))))

(defun depth-dragon-curve (x0 y0 x1 y1 depth handedness)
  "See p. 348, 'LISP'."
  (if (zerop depth)
      (send *window* :draw-lines tv:alu-ior (round x0) (round y0) (round x1) (round y1))
      (let* ((newpoint (+ (* *square-root-of-two-over-two*
			     (if (= handedness 1)
				 *45-degree-left-rotation*
				 *45-degree-right-rotation*)
			     (complex (- x1 x0) (- y1 y0)))
			  (complex x0 y0)))
	     (xnew     (realpart newpoint))
	     (ynew     (imagpart newpoint)))
	(depth-dragon-curve x0 y0 xnew ynew (1- depth) +1)
	(depth-dragon-curve xnew ynew x1 y1 (1- depth) -1))))

(defun funny-curve (length angle min-length handedness)
  (if (< length min-length)
      (plot-line length angle)
      (progn
	(funny-curve (* length *square-root-of-two-over-two*)
		      (+ angle (* handedness *pi-over-four*))
		      min-length
		      (- handedness))
	(funny-curve (* length *square-root-of-two-over-two*)
		      (- angle (* handedness *pi-over-four*))
		      min-length
		      (+ handedness)))))

(defun plot-line (length angle)
  (let* ((dx (* length (cos angle)))
	 (dy (* length (sin angle)))
	 (x2 (round (+ *x* dx)))
	 (y2 (round (+ *y* dy))))
    (send *window* :draw-line *x* *y* x2 y2)
    (setq *x* x2)
    (setq *y* y2)))

(defun center ()
  (setq *x* 300)
  (setq *y* 300))

(eval-when (eval) #'try)
(NAMED-LAMBDA TRY NIL (BLOCK TRY (CENTER) (DRAGON-CURVE 200 0 3 1) (DRAGON-CURVE 200 0 2 1) (CENTER) (DRAGON-CURVE 200 PI 2 1) (CENTER) (DRAGON-CURVE 200 (* PI 1/2) 1 1) (CENTER) (DRAGON-CURVE 200 (* PI 3/2) 1 1)))

(dragon-curve 
(eval-when (eval)
  (center)
  (setq *x* (+ 200 *x*))
  (dragon-curve 200 (* pi 3/4) 2 1))

(defun dragon-iter ()
  (let ((i 0)
	(length 500)
	(x0 200)
	(y0 200))
    (loop
      (let ((char (read-char)))
	(cond
	  ((char= char #\Page)
	   (send *window* :clear-window))
	  ((char= char #\Resume)
	   (send *window* :clear-window)
	   (incf i))
	  ((char= char #\Overstrike)
	   (let ((xleft  (round (- x0 (* length 1/3))))
		 (ytop   (round (- y0 (* length 1/3))))
		 (xright (round (+ x0 (* length 7/6))))
		 (ybot   (round (+ y0 (* length 2/3)))))
	     (send *window* :draw-lines tv:alu-ior
		   xleft ytop xright ytop xright ybot xleft ybot xleft ytop)))
	  (t
	   (incf i))))
;      (setq *x* x0)
;      (setq *y* y0)
      (depth-dragon-curve 200 200 700 200 i 1))))

