
// Dragon.java
// Stefania Bergljot Stefansdottir, 2015
// Slightly reformatted by Andrew Davison, Nov. 2022

// https://introcs.cs.princeton.edu/java/15inout/Dragon.java.html

/* Draws a dragon curve (http://en.wikipedia.org/wiki/Dragon_curve)

   Usage:
     > compile Dragon.java
     > run Dragon n
   e.g.
     > run Dragon 6
*/


import java.util.*;


public class Dragon
{  

  public static void main(String[] args)
  {
    if (args.length != 1) {
      System.out.println("Usage: run Dragon <no. of levels>");
      return;
    }
    int n = Integer.parseInt(args[0]);     // number of levels

    ArrayList<Integer> sequence = new ArrayList<Integer>();
    sequence.add(3);
    sequence.add(1);

    int lvlCount = 1;
    double scale = 2;
    for (int i = 0; i < n; i++) {
      lvlCount++;
      sequence = nextCurve(sequence);
      if (lvlCount%2 != 0)
        scale = (2 * scale+1);
    }
    draw(sequence, scale);
  }  // end of main



  private static ArrayList<Integer> nextCurve(
                             ArrayList<Integer> prevSeq)  
  // generates the next sequence
  {
    boolean isClockwise = true;
    ArrayList<Integer> seq = new ArrayList<Integer>();
    for (int i : prevSeq) {
      if(isClockwise) {
        seq.add((i+1) % 8);
        seq.add((i+7) % 8);
      }
      else {
        seq.add((i+7) % 8);
        seq.add((i+1) % 8);
      }
      isClockwise = !isClockwise;
    }
    return seq;
  } /* nextCurve */


  private static void draw(ArrayList<Integer> sequence, 
                           double scale)
  {
    double d = 1.0 / (scale * 1.2);
    double xc = 0.2, yc = 0.6;
    StdDraw.setCanvasSize(800, 800);

    for (int i : sequence)
      switch (i) {
      case 0:  StdDraw.line(xc, yc, xc, yc+d);
        yc += d;
        break;
      case 1:  StdDraw.line(xc, yc, xc+d, yc+d);
        yc += d; xc += d;
        break;
      case 2:  StdDraw.line(xc, yc, xc+d, yc);
        xc += d;
        break;
      case 3:  StdDraw.line(xc, yc, xc+d, yc-d);
        yc -= d; xc += d;
        break;
      case 4:  StdDraw.line(xc, yc, xc, yc-d);
        yc -= d;
        break;
      case 5:  StdDraw.line(xc, yc, xc-d, yc-d);
        yc -= d; c -= d;
        break;
      case 6:  StdDraw.line(xc, yc, xc-d, yc);
        xc -= d;
        break;
      case 7:  StdDraw.line(xc, yc, xc-d, yc+d);
        yc += d; xc -= d;
        break;
      } /* switch */
  } /* draw */


}  // end of Dragon class