import java.awt.*; import java.applet.AppletContext; import java.lang.Exception; import java.lang.Object; import java.util.StringTokenizer; import java.io.*; public class Life extends java.applet.Applet implements Runnable { int grid[][][]; int atgrid = 0; int gridsize = 4; boolean paused = true; boolean statusShown = true; Thread recalc; Image offScrImage; Graphics offScrGC; int lastx = -1 ,lasty = -1; int side = 50; int generation = 0; int delay = 0; public void init() { if (getParameter("side") != null) side = (new Integer(getParameter("side"))).intValue(); if (getParameter("gridsize") != null) gridsize = (new Integer(getParameter("gridsize"))).intValue(); else if (side < 70) gridsize = 8; else gridsize = 4; resize(side*gridsize,side*gridsize); grid = new int[2][side][side]; try { if (getParameter("initstate") != null) { StringTokenizer Points = new StringTokenizer (getParameter ("initstate"),"\t\n\r ,;."); while (Points.hasMoreTokens()) { grid[0][(new Integer(Points.nextToken())).intValue()] [(new Integer(Points.nextToken())).intValue()] = 1; } } if ((getParameter("random") != null) && ((new Boolean(getParameter("random"))).booleanValue())) { int b, c; for (b = 0; b < side; b++) for (c = 0; c < side; c++) grid[0][b][c] = (int) (Math.random() * 1.2); } if ((getParameter("paused") != null) && !((new Boolean(getParameter("paused"))).booleanValue())) switchPause(); if (getParameter("delay") != null) delay = (new Integer(getParameter("delay"))).intValue(); } catch (Exception e) {} } public void dorecalc() { int x,y,a,atsum,atlast; int last[] = new int[3]; int atg = (atgrid + 1) % 2 ; generation++; for (y = 0; y < side; y++) { last[0] = 0; last[1] = 0; for (a = -1; a <= 1; a++) { last[0] += grid[atgrid][side-1][(y+side+a) % side]; last[1] += grid[atgrid][0][(y+side+a) % side]; } atlast = 1; for (x = 0; x < side; x++) { atlast = (atlast+1) % 3; int nx = (x+1) % side; last[atlast] = grid[atgrid][nx][(y+side-1)%side]+ grid[atgrid][nx][y]+ grid[atgrid][nx][(y+1)%side]; atsum = 0; for (a = 0; a < 3; a++) atsum += last[a]; if (grid[atgrid][x][y] == 1) { if ((atsum > 2) && (atsum < 5)) grid[atg][x][y] = 1; else grid[atg][x][y] = 0; } else { if (atsum == 3) grid[atg][x][y] = 1; else grid[atg][x][y] = 0; } } } synchronized (this) { atgrid = atg; } updateStatus(false); } public String getAppletInfo() { return "Written by Andreas Ehrencrona (d95-aeh@nada.kth.se)"; } public String[][] getParameterInfo() { String[][] params = {{"side","integer","Sidlängd"}, {"gridsize","integer","Storlek på rutor"}, {"initstate","string","Lista på koordinater"}, {"paused","string","Om true så är simulationen pausad vid start"}}; return params; } public boolean mouseDown(java.awt.Event evt, int x, int y) { if (x >= side*gridsize-16) { if (y >= side*gridsize-16) { switchPause(); paintButton(offScrGC); repaint(); } else if (y >= side*gridsize-32) { if (!paused) switchPause(); int a, b, c; atgrid = (atgrid+1) % 2; for (b = 0; b < side; b++) for (c = 0; c < side; c++) grid[atgrid][b][c] = 0; generation = 0; paintButton(offScrGC); updateOffScr(offScrGC); repaint(); } else if (y >= side*gridsize-48) { if (!paused) switchPause(); int b, c; atgrid = (atgrid+1) % 2; for (b = 0; b < side; b++) for (c = 0; c < side; c++) grid[atgrid][b][c] = (int) (Math.random() * 1.2); generation = 0; paintButton(offScrGC); updateOffScr(offScrGC); repaint(); } else { toggleCell(x / gridsize, y / gridsize); } } else { toggleCell(x / gridsize, y / gridsize); } return false; } public boolean mouseDrag(Event evt, int x, int y) { int a = x / gridsize; int b = y / gridsize; if ((a != lastx) || (b != lasty)) toggleCell(a, b); return false; } public boolean mouseExit(java.awt.Event evt, int x, int y) { showStatus(""); statusShown = true; return false; } public boolean mouseMove(java.awt.Event evt, int x, int y) { if ((x >= side*gridsize-16) && (y >= side*gridsize-48)) { statusShown = true; if (y >= side*gridsize-16) showStatus(paused ? "Press to start the simulation." : "Press to pause the simulation."); else if (y >= side*gridsize-32) showStatus("Press to clear the field."); else showStatus("Press to fill the field with random squares."); } else if (statusShown) updateStatus(true); return false; } public boolean mouseUp(java.awt.Event evt, int x, int y) { lastx = -1; lasty = -1; return false; } public void paint(Graphics g) { if (offScrImage != null) { g.drawImage(offScrImage,0,0,this); } } public synchronized void paintButton(Graphics g) { g.setColor(new Color(220,220,156)); g.fill3DRect(side*gridsize-16,side*gridsize-16,16,16,!paused); g.fill3DRect(side*gridsize-16,side*gridsize-32,16,16,true); g.fill3DRect(side*gridsize-16,side*gridsize-48,16,16,true); g.setColor(Color.gray); int a = paused ? 1 : 0; g.fillRect(side*gridsize-12+a,side*gridsize-13,2,9); g.fillRect(side*gridsize- 7+a,side*gridsize-13,2,9); g.drawString("C",side*gridsize-11,side*gridsize-19); g.drawString("R",side*gridsize-11,side*gridsize-35); } public void paintGrid(Graphics g) { int x,y,a,b; int width = side * gridsize; g.setColor(Color.white); g.fillRect(0,0,width,width); g.setColor(new Color(0, 0, 255)); for (x = 0; x < width; x += gridsize) { g.drawLine(x,0,x,width); } for (y = 0; y < width; y += gridsize) { g.drawLine(0,y,width,y); } } public void run() { while (true) { synchronized (this) { dorecalc(); } updateOffScr(offScrGC); repaint(); try { Thread.currentThread().sleep(delay+50); } catch (InterruptedException e){} } } public void start() { offScrImage = createImage(side*gridsize, side*gridsize); offScrGC = offScrImage.getGraphics(); paintGrid(offScrGC); paintButton(offScrGC); updateOffScr(offScrGC); repaint(); if (!paused && (recalc == null)) { try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) {} recalc = new Thread(this); recalc.start(); } } public void stop() { if (recalc != null) { recalc.stop(); recalc = null; } } public void switchPause() { paused = !paused; if (paused) { recalc.stop(); recalc = null; } else { recalc = new Thread(this); recalc.start(); } } public void toggleCell(int a, int b) { Graphics g; g = getGraphics(); if ((a < side) && (b < side) && ((a < (side*gridsize - 16)/gridsize) || (b < (side*gridsize - 48)/gridsize))) { int newval = (grid[atgrid][a][b]+1) % 2; grid[atgrid][a][b] = newval; if (grid[atgrid][a][b] == 1) g.setColor(new Color(0,0,0)); else g.setColor(new Color(255,255,255)); g.fillRect(a * gridsize + 1, b * gridsize +1, gridsize-1, gridsize-1); } lastx = a; lasty = b; } public void update(Graphics g) { paint(g); } public synchronized void updateOffScr(Graphics g) { int x, y, a, b; int atg = (atgrid+1) % 2; int rmarg = 16 / gridsize; int bmarg = 3*rmarg; if (g == null) return; if (16 % gridsize != 0) { rmarg++; bmarg++; } rmarg = side - rmarg; bmarg = side - bmarg; b = side; for (x = 0; x < side; x++) { if ((x >= rmarg) && (b > bmarg)) b = bmarg; for (y = 0; y < b; y++) { if (grid[atg][x][y] != grid[atgrid][x][y]) { if (grid[atgrid][x][y] == 1) g.setColor(Color.black); else g.setColor(Color.white); g.fillRect(x*gridsize+1, y*gridsize+1, gridsize-1, gridsize-1); } } } } public void updateStatus(boolean force) { if (!statusShown || force) { statusShown = false; showStatus(paused ? "Paused." : "Running. Generation "+generation+"."); } }}