// Copyright 2002 Bobby Williams - www.JoyAndBobby.com // Released under the GNU General Public License - www.gnu.org import java.awt.*; import java.awt.event.*; import java.applet.*; public class AutomataApplet extends Applet { Choice sizeChooser; int cellSize = 10; int height = 400; int width = height * 2; int[][] cells; Checkbox ruleBits[] = new Checkbox[8]; Label ruleLabel; MyCanvas canvas = new MyCanvas(); public AutomataApplet() { canvas.setSize(width, height); canvas.setBackground(Color.white); Panel panel = new Panel(new BorderLayout()); panel.add(canvas, BorderLayout.CENTER); panel.add(new Panel(), BorderLayout.SOUTH); //buffer panel panel.setVisible(true); Panel controlPanel = new Panel(new BorderLayout()); Panel rulePanel = new Panel(new GridLayout(1,9)); for (int i = 0; i < ruleBits.length; i++) { ruleBits[i] = new BitCheckbox(i); rulePanel.add(ruleBits[i]); ruleBits[i].setBounds(i * 55,10,51,51); } controlPanel.add(rulePanel, BorderLayout.CENTER); ruleLabel = new Label("Rule ####"); Panel labelPanel = new Panel(); labelPanel.add(ruleLabel); controlPanel.add(labelPanel, BorderLayout.WEST); sizeChooser = new Choice(); sizeChooser.add("1"); sizeChooser.add("2"); sizeChooser.add("4"); sizeChooser.add("8"); sizeChooser.add("16"); sizeChooser.select(2); Panel sizePanel = new Panel(); sizePanel.add(new Label("Cell Size:")); sizePanel.add(sizeChooser); sizePanel.add(new Label(" ")); //cheap spacer Button go = new Button("Show Me"); go.setSize(50,50); go.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { initCells(); Graphics graphics = canvas.getGraphics(); graphics.setColor(canvas.getBackground()); graphics.fillRect(0,0,width,height); runAutomata(); } }); sizePanel.add(go); sizePanel.add(new Label(" ")); //cheap spacer controlPanel.add(sizePanel, BorderLayout.EAST); this.setLayout(new BorderLayout()); this.add(panel, BorderLayout.NORTH); this.add(controlPanel, BorderLayout.CENTER); this.setBackground(Color.white); this.setVisible(true); } void initCells() { cellSize = Integer.parseInt(sizeChooser.getSelectedItem().toString()); cells = new int[height / cellSize][width / cellSize]; for (int row = 0; row < cells.length; row++) for (int col = 0; col < cells[row].length; col++) cells[row][col] = -1; } boolean[] makeBits(int value, int length) { boolean[] bits = new boolean[length]; int power = (new Double(Math.pow(2,length))).intValue(); for (int i = 0; i < bits.length; i++) { power = power / 2; if (value >= power) { bits[i] = true; value -= power; } else bits[i] = false; } return bits; } int getRuleNumber() { int number = 0; int power = 1; for (int i = 0; i < ruleBits.length; i++) { if (ruleBits[i].getState()) number += power; power = power * 2; } return number; } void runAutomata(int ruleNum) { boolean[] bits = makeBits(ruleNum, 8); for (int i = 0; i < ruleBits.length; i++) ruleBits[i].setState(bits[7-i]); //bugfix: flipped bit order runAutomata(); } void runAutomata() { ruleLabel.setText("Rule #" + getRuleNumber()); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); initCells(); int[] startSpots = {height / cellSize}; for (int i = 0; i < startSpots.length; i++) { canvas.getGraphics().fillRect(startSpots[i] * cellSize, 0, cellSize,cellSize); cells[0][startSpots[i]] = 8; } for (int row = 1; row < cells.length; row++) for (int col = 0; col < cells[row].length; col++) { boolean left, center, right; if (col != 0) left = cells[row-1][col-1] > -1; else left = cells[row-1][cells[row-1].length-1] > -1; center = cells[row-1][col] > -1; if (col != cells[row-1].length-1) right = cells[row-1][col+1] > -1; else right = cells[row-1][0] > -1; if (left) if (center) if (right) addCell(row,col,7); else addCell(row,col,6); else if (right) addCell(row,col,5); else addCell(row,col,4); else if (center) if (right) addCell(row,col,3); else addCell(row,col,2); else if (right) addCell(row,col,1); else addCell(row,col,0); } this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } void addCell(int row, int col, int cellRule) { if (!(ruleBits[cellRule].getState())) return; cells[row][col] = cellRule; Graphics graphics = canvas.getGraphics(); graphics.fillRect(col * cellSize,row * cellSize,cellSize,cellSize); } public void init() { runAutomata(30); } class MyCanvas extends Canvas { public void paint(Graphics g) { for (int x = 0; x < cells.length; x++) for (int y = 0; y < cells[x].length; y++) if (cells[x][y] != -1) g.fillRect(y * cellSize,x * cellSize,cellSize,cellSize); } } class BitCheckbox extends Checkbox { boolean valueBits[]; public BitCheckbox(int value) { this.setBackground(Color.white); valueBits = makeBits(value,3); this.addMouseListener(new MouseAdapter() { public void mouseEntered(MouseEvent e) { BitCheckbox.this.setCursor(Cursor.getPredefinedCursor( Cursor.HAND_CURSOR)); } public void mouseExited(MouseEvent e) { BitCheckbox.this.setCursor(Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR)); } }); } public void paint(Graphics g) { g.setColor(this.getBackground()); g.fillRect(0,0,this.getWidth(),this.getHeight()); g.setColor(this.getForeground()); for (int i = 0; i < valueBits.length; i++) if (valueBits[i]) g.fillRect(i*15+2,0,15,16); else g.drawRect(i*15+2,0,15,15); if (this.getState()) g.fillRect(17,17,15,15); else g.drawRect(17,17,15,15); } } }