import java.awt.*;
import java.applet.*;
import java.util.Random;
import java.lang.Math;
import java.util.*;
import java.lang.Thread;
import java.lang.Integer;
import java.lang.String;


class Node {
    int x;
    int y;
    int dx;
    int dy;
    boolean fixed;
    String lbl;
public	int xcoor;
public	int ycoor;
public	int[] erasex;	        
public	int[] erasey;
public	int trailconstant;
public int[] instructions;
public	int number_of_instructions;
int my_age;
public	int which_am_i;
public	int placeholder;
Random myrand;	
public int eraseflag;
int iterations;
int currenttrail;
int agecap;
}

class GraphPanel extends Panel implements Runnable {
Graph graph;
int NNODES;
final int CREATUREMAX = 10;
int CLOCKMAX = 800;
int INSTRUCTIONSMAX = 1000;
    Node nodes[] = new Node[100];
    int nedges;

    Thread relaxer;
    boolean stress;
    boolean random;

    GraphPanel(Graph graph) {
        this.graph = graph;
    }



    int addNode(String lbl, int t, int t2, int t3) {
		int theint;
		Random therand;
        Node n = new Node();
     nodes[NNODES] = n;

	nodes[NNODES].lbl = lbl;   
	nodes[NNODES].my_age = 0;
	nodes[NNODES].currenttrail = t2;
	nodes[NNODES].agecap = t3;
	nodes[NNODES].iterations = 0;
nodes[NNODES].instructions = new int[INSTRUCTIONSMAX];
nodes[NNODES].erasex = new int[n.currenttrail];
nodes[NNODES].erasey = new int[n.currenttrail];
nodes[NNODES].my_age = 0;
// my_age is misleading.. it's used, but iterations is now the age
therand = new Random();

		nodes[NNODES].which_am_i = NNODES;

	nodes[NNODES].number_of_instructions= (Math.abs(therand.nextInt() % INSTRUCTIONSMAX))+1;
// OVERRIDE!!!!!
//Integer x = Integer.getInteger(t);
nodes [NNODES].number_of_instructions = t;
		

		 		if (nodes[NNODES].number_of_instructions == 1)									 
			{
			nodes[NNODES].number_of_instructions = 2;		
			}


		for (int instructionmaker = 0 ; instructionmaker < (nodes[NNODES].number_of_instructions); instructionmaker++)		
		{
		theint = Math.abs(therand.nextInt() % 9);	
		
		nodes[NNODES].instructions[instructionmaker] = theint;	
	while (nodes[NNODES].instructions[instructionmaker] == 8) { nodes[NNODES].instructions[instructionmaker]= Math.abs((therand.nextInt() * 10000) % 9);	}		
		}	
		nodes[NNODES].xcoor = Math.abs((therand.nextInt()) % 200);
		nodes[NNODES].ycoor = Math.abs((therand.nextInt()) % 200);





		return NNODES++;




    }



    void addEdge(String from, String to, int len) {
    }

    public void run() {
        while (true) {
            relax();
            
            }

        }
    
    synchronized void relax() {

        repaint();
    }

    Node pick;
    boolean pickfixed;
    Image offscreen;
    Dimension offscreensize;
    Graphics offgraphics;
    



    public void paintNode(Graphics g, Node n, FontMetrics fm) {
		
		int joker;
		int pendingcharacter;
		int theint;

		//CURRENTTRAIL = 10;

if (n.my_age == 0 )
{
Random wiggy;
wiggy = new Random();


	n.number_of_instructions= (Math.abs(wiggy.nextInt() % INSTRUCTIONSMAX))+1;
	
				 		if (n.number_of_instructions == 1)									 
			{
			n.number_of_instructions = 2;		
			}
		for (int instructionmaker = 0 ; instructionmaker < (n.number_of_instructions); instructionmaker++)		
		{
		theint = Math.abs(wiggy.nextInt() % 9);	
		n.instructions[instructionmaker] = theint;	
	while (n.instructions[instructionmaker] == 8) { n.instructions[instructionmaker]= Math.abs((wiggy.nextInt() * 10000) % 9);	}		
		}	
		n.xcoor = Math.abs(wiggy.nextInt() % 200);
		n.ycoor = Math.abs(wiggy.nextInt() % 200);
		
n.my_age++;
}


pendingcharacter = n.instructions[0];
n.iterations++;
switch (pendingcharacter)
{
case 0:
n.xcoor--;
n.ycoor--;
break;

case 1:
n.xcoor--;

break;

case 2:
n.xcoor--;
n.ycoor++;
break;

case 3:
n.ycoor++;
break;

case 4:
n.xcoor++;
n.ycoor++;
break;

case 5:

n.xcoor++;
break;

case 6:
n.xcoor--;
n.ycoor++;
break;

case 7:
n.ycoor--;
break;
}

if (n.xcoor < 2)
{
n.xcoor = 398;
}

if (n.xcoor > 398)
{
n.xcoor = 2;
}

if (n.ycoor < 2)
{
n.ycoor = 398;
}

if (n.ycoor > 398)
{
n.ycoor = 2;
}







if (n.iterations <= n.currenttrail)

{

// put here now
//g.setColor(Color.red);
//g.drawString(".",n.erasex[0], n.erasey[0]);
//g.setColor(Color.red);
// put here now

n.erasex[n.iterations-1] = n.xcoor;
n.erasey[n.iterations-1] = n.ycoor;
}


if (n.iterations > n.currenttrail)

{

g.setColor(Color.white);
g.drawString(n.lbl,n.erasex[0], n.erasey[0]);
g.setColor(Color.black);


for (int restofarray = 0; restofarray < n.currenttrail-1; restofarray++)
{
n.erasex[restofarray] = n.erasex [restofarray + 1];
n.erasey[restofarray] = n.erasey [restofarray + 1];
}

n.erasex[n.currenttrail-1] = n.xcoor;
n.erasey[n.currenttrail-1] = n.ycoor;


}


int upperlimit = (n.number_of_instructions)-1;




for (int newINDEX = 0; newINDEX < upperlimit; newINDEX++)
{



n.instructions[newINDEX] = n.instructions[(newINDEX+1)];

}
n.instructions[upperlimit] = pendingcharacter;



g.setColor(Color.black);


if (n.which_am_i > 0) 
{
	if (n.iterations < n.agecap)
	{
		g.drawString (n.lbl, n.xcoor,n.ycoor);    
	}	
}



    }



    public synchronized void update(Graphics g) {

        Dimension d = size();
        if ((offscreen == null) || (d.width != offscreensize.width) || (d.height != offscreensize.height)) {
            offscreen = createImage(d.width, d.height);
            offscreensize = d;
            offgraphics = offscreen.getGraphics();
            offgraphics.setFont(getFont());
        }

       // offgraphics.setColor(Color.green);
       // offgraphics.fillRect(0, 0, d.width, d.height);
   FontMetrics fm = offgraphics.getFontMetrics();
        for (int i = 0 ; i < NNODES ; i++) {
       



if (nodes[0].eraseflag == 5)
{
        //offgraphics.setColor(Color.yellow);
        //offgraphics.fillRect(0, 0, d.width, d.height);
		offgraphics.setColor (Color.pink);
		nodes[0].eraseflag = 0;
}






            if (stress) {


				 if (nodes[i].which_am_i > 0)
				{
				//String lbl =  nodes[i].lbl;
		

				offgraphics.setColor(Color.black);
                //offgraphics.drawString(lbl, nodes[i].xcoor+10, nodes[i].ycoor+10);

			//offgraphics.setColor(Color.white);
//			offgraphics.drawString(lbl, nodes[i].xcoor+10, nodes[i].ycoor+10);    
//        offgraphics.setColor(Color.white);
//        offgraphics.fillRect(0, 0, d.width, d.height);


				}
			}
// added right now
	//	nodes[i].my_age++;
// added right now

        }

 
        for (int i = 0 ; i < NNODES ; i++) {
offgraphics.setColor(Color.black);
	    paintNode(offgraphics, nodes[i], fm);
	}

        g.drawImage(offscreen, 0, 0, null);
    }


    public void start() {
        relaxer = new Thread(this);
        relaxer.start();
    }
    public void stop() {
        relaxer.stop();
    }
}





public class Graph extends Applet {
    GraphPanel panel;
	Random numcreatures;
	int pendingcharacter;
	//int n.currenttrail = 10;
	final int CREATUREMAX = 2;
	final int INSTRUCTIONSMAX = 1000;

	TextField	t = new TextField ("10", 5);
	TextField   t2 = new TextField ("10", 5);
	TextField   t3 = new TextField ("10", 5);


    
	public void init() {
        setLayout(new BorderLayout());
	
        panel = new GraphPanel(this);
        add("Center", panel);
        Panel p = new Panel();
        add("South", p);
        p.add(new Button("Scramble"));

        p.add(new Checkbox("Stress"));

		p.add(t);
		p.add(t2);
		p.add(t3);



int edges2 = CREATUREMAX;
int whatitwas;



	panel.addNode ("x",5,5,5);
	
   }




    public void start() {
        panel.start();
    }
    public void stop() {
        panel.stop();
    }
    public boolean action(Event evt, Object arg) {
        if (arg instanceof Boolean) {
            if (((Checkbox)evt.target).getLabel().equals("Stress")) {
                panel.stress = ((Boolean)arg).booleanValue();
            } 
			
            return true;
        } 
        if ("Scramble".equals(arg)) {

	String s = new String();
	String s2 = new String();
	String s3 = new String();
	s = t.getText();
	s2 = t2.getText();
	s3 = t3.getText();
   int news = Integer.parseInt (s);
	int news2 = Integer.parseInt (s2);
	int news3 = Integer.parseInt (s3);

	getAppletContext().showStatus (t.getText());	
	//panel.nodes[0].eraseflag = 5;
          
            for (int i = 0 ; i < panel.NNODES ; i++) {
                Node n = panel.nodes[i];
                if (!n.fixed) {

n.my_age--;




if (n.my_age == 0 )


{
	panel.addNode (".",news, news2, news3);


}

pendingcharacter = n.instructions[0];

switch (pendingcharacter)
{
case 0:
n.xcoor--;
n.ycoor--;
break;

case 1:
n.xcoor--;
break;

case 2:
n.xcoor--;
n.ycoor++;
break;

case 3:
n.ycoor++;
break;

case 4:
n.xcoor++;
n.ycoor++;
break;

case 5:
n.xcoor++;
break;

case 6:
n.xcoor--;
n.ycoor++;
break;

case 7:
n.ycoor--;
break;
}

if (n.xcoor < 2)
{
n.xcoor = 398;
}

if (n.xcoor > 398)
{
n.xcoor = 2;
}

if (n.ycoor < 2)
{
n.ycoor = 398;
}

if (n.ycoor > 398)
{
n.ycoor = 2;
}






if (n.iterations <= n.currenttrail)

{
n.erasex[n.iterations-1] = n.xcoor;
n.erasey[n.iterations-1] = n.ycoor;
}


if (n.iterations > (n.currenttrail))

{







for (int restofarray = 0; restofarray < n.currenttrail-1; restofarray++)
{
n.erasex[restofarray] = n.erasex [restofarray + 1];
n.erasey[restofarray] = n.erasey [restofarray + 1];
}

n.erasex[n.currenttrail-1] = n.xcoor;
n.erasey[n.currenttrail-1] = n.ycoor;


}


int upperlimit = (n.number_of_instructions)-1;




for (int newINDEX = 0; newINDEX < upperlimit; newINDEX++)
{



n.instructions[newINDEX] = n.instructions[(newINDEX+1)];

}
n.instructions[upperlimit] = pendingcharacter;









                }
            }
            return true;
        }

 return false;
}}
