/* Class Fold immitates a strip of paper being folded and unfolded
so that all folds are 90 degrees.
Shown in the hardcover version of Jurassic Park.
Nice fractal

Written by Michael Mandel

	Last change:  MM    4 Mar 2000    7:14 pm
 */


import java.awt.*;
import java.lang.*;

public class Fold extends java.applet.Applet implements Runnable{
    private int REPS;
    private int LINESTART;

    private static final int NORTH = 0;
    private static final int EAST = 1;
    private static final int SOUTH = 2;
    private static final int WEST = 3;
    private static final int LEFT = -1;
    private static final int RIGHT = 1;

    private int lineLength, lineCount = 1;
    private int[] array, newArray;
    private int startX, startY, width, height;

    private Image doubleBuffer;
    private boolean dbChanged = true;

    public void init()
    {
		array = new int[0];
		newArray = new int[1];

		REPS = Integer.parseInt(getParameter("reps"));
		LINESTART = Integer.parseInt(getParameter("lineStart"));
		
		new Thread(this).start();
    }
    
    public void run()
    {
    		for(int x = 0; x < REPS; x ++)
			{
		   	iterate();
		   	repaint();
	  	   	try{Thread.sleep(1000);} catch(Exception ignored){};
			}
	  }

    public void iterate()
    {
    	int x;

		for(x = 0; x < array.length; x++)
			    if(array[x] == LEFT || array[x] == RIGHT)
			    	newArray[x] = array[x];

		newArray[x] = RIGHT;

		x = 1;
		while(x <= array.length)
		{
		    if(array[array.length - x] == RIGHT)
				newArray[array.length + x] = LEFT;
		    else if(array[array.length - x] == LEFT)
				newArray[array.length + x] = RIGHT;
		    x++;
		}

		array = new int[newArray.length];
		for(x = 0; x < array.length; x++)
		    array[x] = newArray[x];
		newArray = new int[array.length * 2 + 1];
	
		lineLength = LINESTART / lineCount;
		lineCount++;
	
		dbChanged = true;
    }

    private void getDimensions()
    {
		int count, direction = NORTH;
		int x= 0, y = -lineLength, minX = 0, minY = -lineLength, maxX = 0, maxY = 0;
	
	   for (count = 0; count < array.length; count++)
		{
		    direction = (direction + array[count] + 4) % 4;
	
		    switch ( direction )
		    {
				case NORTH :
					y -= lineLength;
				    break;
				case SOUTH :
					y += lineLength;
				    break;
				case EAST :
					x += lineLength;
				    break;
				case WEST :
					x -= lineLength;
				    break;
				default :
				    break;
		    }
	
		    if(x > maxX)
				maxX = x;
		    if(y > maxY)
				maxY = y;
		    if(x < minX)
				minX = x;
		    if(y < minY)
				minY = y;
		}
	
		height = maxY - minY + 40;
		width = maxX - minX + 20;
		startX = 10 - minX;
		startY = 30 - minY;
	
		doubleBuffer = createImage(width, height);
    }

    public void drawToDB()
    {
		getDimensions();
	
		Graphics g = doubleBuffer.getGraphics();
	
		int count;
		int direction = NORTH;
		int x, y;

		x = startX;
		y = startY;

		g.fillRect(startX - 3, startY - 3, 6, 6);

		g.drawLine(x, y, x, y - lineLength);
		y -= lineLength;

		for (count = 0; count < array.length; count++)
		{
		    direction = (direction + array[count] + 4) % 4;
	
		    switch ( direction )
		    {
			case NORTH :
				g.drawLine(x, y, x, y - lineLength);
				y -= lineLength;
			    break;
			case SOUTH :
				g.drawLine(x, y, x, y + lineLength);
				y += lineLength;
			    break;
			case EAST :
				g.drawLine(x, y, x + lineLength, y);
				x += lineLength;
			    break;
			case WEST :
				g.drawLine(x, y, x - lineLength, y);
				x -= lineLength;
			    break;
	
			default :
			    break;
		    }
		}
		dbChanged = false;
    }

    public void paint(Graphics g)
    {
    	if(dbChanged)
	    drawToDB();
		g.drawImage(doubleBuffer, 0, 0, this);
    }
}

