import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.lang.*; import java.io.*; /** One-Dimension Cellular Automata * This applet implements One Dimensional Cellular Automata, * first researched by Stephen Wolfram. * The set of CA's implemented are those with a radix of 1. * @author J Scott Cameron */ public class OneDCA extends Applet implements ActionListener,Runnable{ /* awt components */ Button Draw = new Button("Draw"); TextField zoomText = new TextField("1"); Label zoomLabel = new Label("Zoom"); Label initTypeLabel = new Label("Init Type:"); Dimension size; Image buffer; Graphics bufferGraphics; Image buffer2; Image line; Graphics lineGraphics; Graphics bufferGraphics2; Checkbox states[] = new Checkbox[8]; Checkbox scroll, seedInit, randomInit; CheckboxGroup initType; /* random object for Random initialization*/ Random random; /* ints to control size and zoom of CA/graphics */ int xMin, xMax, yMin, yMax; int width,height,zoom; /* Vector that contains the most recent state of the CA */ Vector lastLine; /* lattice to record the state of the CA as it progresses*/ boolean board[][]; /* keeps track of how many generations have passed*/ int generation; /* Thread to control animation */ Thread animator; /* bool for animation control */ boolean restart; /** initializes fields of applet on start-up */ public void init() { /* initialize awt components */ setLayout(null); initType = new CheckboxGroup(); scroll = new Checkbox("scroll", false); seedInit = new Checkbox("seed", true , initType); randomInit = new Checkbox("random",false, initType); random = new Random(); Draw.setBounds(405,5,80,20); Draw.addActionListener(this); add(Draw); zoomLabel.setBounds(415,30,70,20); add(zoomLabel); zoomText.setBounds(415,55,70,20); add(zoomText); scroll.setBounds(415,80,70,20); add(scroll); initTypeLabel.setBounds(415,105,70,20); add(initTypeLabel); seedInit.setBounds(415,130,70,20); add(seedInit); randomInit.setBounds(415,155,70,20); add(randomInit); /* initializes all the rules the "false"*/ for(int i=0;i<8;i++) { states[i] = new Checkbox("",false); states[i].setBounds(523,20+i*40,15,15); add(states[i]); } size = new Dimension(800,410); buffer = createImage(400, 400); bufferGraphics = buffer.getGraphics(); buffer2 = createImage(60,20); bufferGraphics2 = buffer2.getGraphics(); width=400; height=400; zoom=1; line = createImage(width,1); lineGraphics = line.getGraphics(); board = new boolean[width/zoom][height/zoom]; /* initializes the board as empty */ for(int i = 0;i<(width/zoom) ; i++) { for(int j = 0 ; j<(height/zoom) ; j++) { board[i][j]=false; } } } /** overload of update(Graphics) function * calls paint * @param g Graphics object for applet window. */ public synchronized void update(Graphics g) { paint(g); } /** Updates all the graphics for the applet using a buffer swapping technique * for smooth animation. * @param g Graphics object to be painted to, * usually the Graphics object of the main window */ public void paint(Graphics g) { /* clear drawing area and draw outline */ bufferGraphics.setColor(this.getBackground()); bufferGraphics.fillRect(0,0, 399, 399); bufferGraphics.setColor(Color.black); bufferGraphics.drawRect(0,0,399,399); int k; /* this for loops draws the graphics * for the rules boxes */ for(int i=0;i<8;i++) { bufferGraphics2.setColor(this.getBackground()); bufferGraphics2.fillRect(0,0, 59, 19); bufferGraphics2.setColor(Color.black); k=i; for(int j=0;j<3;j++) { if( (k%2) == 0) { bufferGraphics2.drawRect(45-(j*20),5,10,10); } else { bufferGraphics2.fillRect(45-(j*20),5,10,10); } k=k/2; } g.drawImage(buffer2,500,i*40,this); } bufferGraphics.setColor(Color.blue); /* draw the board */ for(int i =0 ; i< (width/zoom) ; i++) { for(int j=0; j<(height/zoom);j++) { if( board[i][j]) { bufferGraphics.fillRect(i*zoom,j*zoom,zoom,zoom); } } } /* draw the buffer to the actual screen */ g.drawImage(buffer,5,5,this); } /** updates the CA vector for one generation */ public synchronized void updateCA() { /* iterates through each cell and checks the * rules to determine the state of the cell * in the next generation */ for(int j=0;j<((width/zoom));j++) { int k=0; if(board[((j-1)+(width/zoom))%(width/zoom)] [(generation-1)%(height/zoom)]) { k+=4; } if(board[j][(generation-1)%(height/zoom)]) { k+=2; } if(board[(j+1)%(width/zoom)][(generation-1)%(height/zoom)]) { k+=1; } board[j][generation%(height/zoom)] = states[k].getState(); } } /** catches the actionEvents (pressed buttons) * and runs the appropriate functions. * @param evt object with information on which button was pressed */ public void actionPerformed(ActionEvent evt) { Button theItem = (Button) evt.getSource(); if (theItem == Draw) DrawPressed(); } /** Starts redrawing CA with new paramaters. */ public void DrawPressed() { /* tell the any animation threads to stop running */ if(animator != null) { if(animator.isAlive()) { restart = true; } } while(restart) {;} generation = 1; /* get the zoom factor*/ zoom = Integer.parseInt(zoomText.getText()); /* reset the animator with a new Thread */ animator = new Thread(this); /* create a buffered image */ line = createImage(width,zoom); lineGraphics = line.getGraphics(); /* make a new board with the correct dimensions * and initilize it to empty */ board = new boolean[width/zoom][height/zoom]; for(int i = 0 ; i< (width/zoom); i++) { for(int j = 0; j < (height/zoom); j++) { board[i][j]=false; } } /* clear the screen */ repaint(5,5,width,height); /*if the "seed" is selected then have the initial vector * be empty except for the center cell */ if(seedInit.getState()) { board[(width/zoom)/2][0] = true; } /* otherwise fill it randomly */ else { for(int i = 0 ; i<(width/zoom) ; i++) { board[i][0] = random.nextBoolean(); } } animator.start(); } /** controls the main animator thread */ public void run() { /* this loop continually unpdates the CA * until another configuration is started * or it hit the bottom of the screen and is * not suppose to scroll */ while(!restart && (scroll.getState() || (generation%(height/zoom) != 0 ))) { updateCA(); /* repaint only the part of the screen affected by the update */ repaint(5,(generation%(height/zoom))*zoom,width,zoom); generation++; try { Thread.sleep(1); } catch(InterruptedException ie) {; } } restart = false; } }