import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.util.Random;


public class ca1d extends Applet implements Runnable, ActionListener
{
  Thread t;
  int y = 60;
  int rule[] = {0,1,0,1,1,0,1,0};
  int oldrow[] = new int[500];
  int newrow[] = new int[500];
  boolean restartQ = true;
  boolean cycleQ = true;
  boolean ICrandomQ = false;
  boolean cyclerulesQ = true;
  boolean skipboringQ = true;
  TextField inrule;
  int ruleint = 90;
  Label rulebin;
  Label diffcountlabel;
  Checkbox CBrules;
  Checkbox CBcycle;
  Checkbox CBIC;
  Checkbox CBskipboring;
  String inputstring = "90";
  String rulebinarystr = "01011010";
  Random rand = new Random();

  public void init()
  {
	newrow[250]=1;  
    t = new Thread(this);
	Button b = new Button("Redraw");
	add(b);
	b.addActionListener(this);
	add(new Label("Enter Rule No."));
	inrule = new TextField(inputstring);
	add(inrule);
	inrule.addActionListener(this);
	rulebin = new Label(rulebinarystr);
	add(rulebin);
	CBrules = new Checkbox("Cycle rules?",cyclerulesQ);
	add(CBrules);
	CBcycle = new Checkbox("Continuous redraw?",cycleQ);
	add(CBcycle);
	CBIC = new Checkbox("Random IC?",ICrandomQ);
	add(CBIC);
	CBskipboring = new Checkbox("Skip static rules?",skipboringQ);
	add(CBskipboring);
	diffcountlabel = new Label("Diffcount:    ");
	add(diffcountlabel);
	t.start();
  }

  public void start()
  {
	  restartQ = true;	  
  }
  
  public void paint(Graphics g)
  {
    y = y + 1;
	if(y > 309)
	{
		docheckboxes();
		if(cycleQ)
		{
	   		restartQ = true;
			if(cyclerulesQ)
			{
				ruleint += 1; 
				if(ruleint == 255)ruleint = 1;
			}
		} 
	}
	if(restartQ){blankscreen(g); restartQ = false;}
	for(int x = 1; x < 499; x++)
	{
	   if(newrow[x]==1)g.fillRect(x,y,1,1);	
	}
    makenewrow();
  }
  
  public void blankscreen(Graphics g)
  {
	 y = 60;
     g.setColor(Color.white);
	 g.fillRect(0,0,500,310);
	 g.setColor(Color.black);
     inputstring = inrule.getText();
	 docheckboxes();
	 makerule();
	 for(int i = 0; i < 500; i++)
	 {
		newrow[i] = 0;
	 }
	 if(ICrandomQ)
	 {
		 for(int i = 0; i < 500; i++)
		 {
			 if(rand.nextFloat() < 0.5F)newrow[i] = 1;
		 }
	 } else newrow[250] = 1;
  }
	  
  public void makenewrow()
  {
	int n = 0;
	for(int i = 0; i < 500; i++)
	{
	    oldrow[i] = newrow[i];	
	}
	int n1 = 499;
	for(int i = 0; i < 500; i++)
	{	
		n = 0;
		if(i == 0) n1 = 499; else n1 = i-1;
		if(oldrow[n1]==1)n+=4;
		if(oldrow[i]==1)n+=2;
		if(i == 499) n1 = 0; else n1 = i + 1;
		if(oldrow[n1]==1)n+=1;
		if(rule[7-n]==1)newrow[i]=1; 
		    else newrow[i]=0;
	}
	int diffcount = 0;
	if(skipboringQ && y == 64)
	{
		for(int i = 0; i < 500; i++)
		{
			if(oldrow[i] != newrow[i])diffcount++;	
		}
		diffcountlabel.setText("Diffcount: "+diffcount);
		if(diffcount < 3 || diffcount > 497)
		{
			restartQ = true;
			ruleint += 1;
			if(ruleint > 255)ruleint = 1;
		}
	}
  }
  
	public void actionPerformed(ActionEvent evt)
	{
		if(evt.getActionCommand().equals("Redraw"))
		{
			restartQ = true;	
			inputstring = inrule.getText();
			ruleint = (new Integer(inputstring)).intValue();
		}
	}
  
	public void makerule()
	{
		
		rulebinarystr = Integer.toBinaryString(ruleint);
		rulebinarystr = "00000000" + rulebinarystr;
		rulebinarystr = rulebinarystr.substring(rulebinarystr.length()-8);
		rulebin.setText(rulebinarystr);
		inrule.setText(new String(""+ruleint));
		int sindex = rulebinarystr.length();
		char position;
		for(int i = 7; i >= 0; i--)
		{
			sindex--;
			position = rulebinarystr.charAt(sindex);
			if(position == '1')rule[i] = 1; else rule[i] = 0;
		}
	}
	
	public void docheckboxes()
	{
		cyclerulesQ = CBrules.getState();
		cycleQ = CBcycle.getState();
		skipboringQ = CBskipboring.getState();
		ICrandomQ = CBIC.getState();
	}
	
	public void update(Graphics g)  //override update method, don't repaint
	{
		paint(g);	
	}

  public void run()
  {
    while(true)
    {
       repaint();
       try
       {
          t.sleep(20);
       } catch(InterruptedException e){}
     }
  }
}