import java.awt.*;
import java.applet.*;
import java.awt.event.*;

/*******************************************************
* SimpleLife: A Java Applet that plays "Conway's Game
* of Life" on a 80x80 grid. Users may start with a
* random configuration (average population density of 0.3)
* and can control the start and stop of each simulation.
* The actual game of life mechanics are implemented in
* a separate class: ConwaysLife.
* The Applet and supplier class were written for a lecture
* on 2D arrays in Java.
* Note no attempt has been made to optimise the drawing
* strategy. Hence generations may go unseen or there may
* be annoying screen flash. This choice was made as it was
* felt that Threads and double-buffering would obscure the
* fundamental purpose of the code (teaching about 2D
* arrays).
* @author Spike Barlow
* @date 25/8/1999
********************************************************/
public class SimpleLife extends Applet implements ActionListener {

  private ConwaysLife	life;
  private final int	PAUSE = 5;
  private Button 	resetButton;
  private Button 	startStopButton;
  private Label 	genLabel;
  private int 		state;
  private final int 	WAITING = 0;
  private final int 	RUNNING = 1;
  private final int	NUM_COLS = 80;
  private final int	NUM_ROWS = 80;
  private final int	PANEL_HEIGHT = 60;
  private final double	POPULATION_DENSITY = 0.3;
  private int		xsize,
			ysize;


/*******************************************************
* init(): Setup the buttons and generate an initial
* distribution for the game (call the ConwaysLife
* constructor).
********************************************************/
public void init() {
  Panel buttonPanel = new Panel();
  setLayout(new BorderLayout());
  startStopButton = new Button("Start");
  startStopButton.setBackground(Color.green);
  startStopButton.addActionListener(this);
  buttonPanel.add(startStopButton);
  resetButton = new Button("Reset");
  resetButton.addActionListener(this);
  buttonPanel.add(resetButton);
  genLabel = new Label("Generation: 0000");
  buttonPanel.add(genLabel);
  add(buttonPanel,"South");
  state = WAITING;
  life = new ConwaysLife(NUM_COLS,NUM_ROWS,POPULATION_DENSITY);
  life.setRowGap(1);
  life.setColumnGap(1);
  Dimension howBig = getSize();
  xsize = howBig.width/NUM_COLS - 1;
  ysize = (howBig.height-PANEL_HEIGHT)/NUM_ROWS - 1;
  xsize = ysize = Math.min(xsize,ysize);
}


/*************************************************************
* actionPerformed(): One of the two buttons was pressed. If
* it was the reset then generate a new population and enter
* the waiting state. If it was the start/stop button then
* toggle the state and alter the Button's label and appearance.
**************************************************************/
public void actionPerformed(ActionEvent e) {
  if (e.getSource()==resetButton) {
    life = new ConwaysLife(NUM_COLS,NUM_ROWS,POPULATION_DENSITY);
    life.setRowGap(1);
    life.setColumnGap(1);
    state = WAITING;
    startStopButton.setLabel("Start");
    startStopButton.setBackground(Color.green);
    repaint();
  }
  else {
    if (state==WAITING) {
      startStopButton.setLabel("Stop");
      startStopButton.setBackground(Color.red);
      state = RUNNING;
      repaint();
    }
    else {
      startStopButton.setLabel("Start");
      startStopButton.setBackground(Color.green);
      state = WAITING;
      repaint();
    }
  }
}


/*************************************************************
* paint(): Get the Game to draw itself to the screen. If we
* are in the running state then advance one generation and
* call repaint() to keep iterating.
*************************************************************/
public void paint(Graphics g) {
  if (state==RUNNING)
    life.advanceGeneration();
  life.draw(g,0,0,xsize,ysize);
  genLabel.setText("Generation: " + life.getGeneration());
  if (state==RUNNING) {
    try {
      Thread.sleep(PAUSE);
    }
    catch (Exception e) { }
    repaint();
  }
}
}


