// mmankins original java
// burt fixed it up
// 8 April 1996
// 9 April: re-radomize on mouse event
// 15 April: reworked screen update -burt
// (c) Burt and Matt 1996 All Rights Reserved


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

public class Life extends Applet
  implements Runnable {
  
  final int SIZE = 50 ;
  int width = SIZE ;
  int height= SIZE ;
  final int BOX = 3 ;
  
  int total_cells = width*height;
  Color colors=Color.red;
  Image offscreen;
  
  int[][] state ;     //define life array  
  int[][] statetemp ; //temp life array
  final int ALIVE = 3 ;
  final int ZOMBIE = 1 ;
  final int DEAD = 0 ;  
  // We must have: DEAD < ZOMBIE < ALIVE 
  
  Thread killme=null;
  private boolean restart_request = false ;

  public void init() {
    state = new int [SIZE][SIZE] ;
    statetemp = new int [SIZE][SIZE] ;  
    offscreen = this.createImage( SIZE*BOX, SIZE*BOX ) ;
    randomize();
  }
  
  public void start() {
    
    if (killme==null) {
        killme=new Thread(this);
        killme.start();
    }
    
  }

  public void stop() {
    if (killme != null) {  
       killme.stop();
    }
    killme=null;
  }
 
  public void randomize() {
    Random rand;
    
    rand = new Random((long)System.currentTimeMillis()) ;
    int i,j,nonsense;
  
    for (i=0; i<SIZE;i++)
      for (j=0; j<SIZE;j++) {   
        nonsense=rand.nextInt();
        state[i][j] = ( nonsense>0 ) ? DEAD : ALIVE ;
     }
  }

  public int neighbors(int ii, int jj ) {  
    int count=0;
    
    ii += SIZE ;
    jj += SIZE ;
    for ( int i=-1; i<2; i++ ) 
      for ( int j=-1; j<2; j++ )
         if ( state[(ii+i)%SIZE][(jj+j)%SIZE] == ALIVE ) count++ ;
         
    if ( state[ii%SIZE][jj%SIZE] == ALIVE ) count-- ;   
    return count ;
    
 }

  //Should I stay, or should I go?
  //The god routine, true == ALIVE
  public int rules(int current, int n) {
    boolean a ;
    if (current==ALIVE)
       a = ((n==2)||(n==3)) ;
    else
       a = (n==3) ;
    if ( a ) return ALIVE ;
    // it's dead, or to die
    if ( current==ALIVE ) return ZOMBIE ;
    if ( current==DEAD ) return DEAD ;
    // else it's a ZOMBIE
    return (current-1) ;

  }

  public void elapse() {
    int i, j ;
    int[][] t ;

    for ( i=0; i<SIZE; i++ )
      for ( j=0; j<SIZE; j++)
          statetemp[i][j] = rules(state[i][j], neighbors(i, j));

    t = state ;
    state = statetemp ;
    statetemp = t ; 
   
 }  
  
 public void run() {
    int i,j;
    int nonsense;

    while(killme != null) {

     if ( restart_request ) randomize() ;
     restart_request = false ;
  
     elapse();

     Graphics g = offscreen.getGraphics();

     g.setColor(Color.blue) ;
     g.fillRect(0,0,SIZE*BOX,SIZE*BOX) ;
     g.setColor(Color.red) ;
     for (i=0; i<SIZE;i++)
        for (j=0; j<SIZE;j++)
          if ( state[i][j] == ALIVE )
             g.fillRect(i*BOX,j*BOX,BOX,BOX) ;

      //Copy it all at once to the screen
      repaint() ;
      
      try {
        Thread.currentThread().sleep(1000);
      }
      catch (InterruptedException e) {
      }
      
    
    } //while
  }

  public void update( Graphics g ) {
      paint(g) ;
  }

  public void paint( Graphics g ) {
      g.drawImage( offscreen, 0, 0, null ) ; 
      //  g.drawImage( offscreen, 0, 0, this ) ;
  } 
 
  public boolean mouseUp( Event ev, int x, int y ) {
     restart_request = true ;
     return true ;
  }

  public String getAppletInfo() {
      return "Life by Matt Mankins and Burt Rosenberg" ;
   }

}




