/* Conway's Life Generator for Java. (11-Jan-97 revision) Copyright 1996-97 by Paul B. Callahan, callahan@inf.ethz.ch */ import java.util.*; import java.awt.*; import java.awt.image.ImageObserver; import java.awt.image.PixelGrabber; class generator { int CellList[], n; int a[]; int b[]; int c[]; int generations; Color background; Color foreground; Color livecell; Color deadcell; Color border; int statusheight; int displaywidth; int displayheight; int cellsize; int originx; int originy; int maxcells; static int countmsk=0x1f; static int posmsk=0x7fffffe0; static int maxval=0x7fffffff; String statusLine; String loading; int scroll; static boolean rules[]={ false, false, false, false, false, true, true, true, false, false, false, false, false, false, false, false, false, false }; public generator() { n=0; generations=0; maxcells=0; background=Color.white; foreground=Color.black; originx=0; originy=0; loading=null; scroll=10; cellsize=2; statusLine=new String(""); } public void loading(String init_loading) { loading=init_loading; } public void setScroll(int init_scroll) { scroll=init_scroll; } public void setColors(Color init_background, Color init_foreground, Color init_border) { background=init_background; foreground=init_foreground; border=init_border; } public void setCellColors(Color init_deadcell, Color init_livecell) { deadcell=init_deadcell; livecell=init_livecell; } public void setDisplaySize(int width, int height) { statusheight=35; displaywidth=width; displayheight=height-statusheight; } public void translate(int dx, int dy) { originx+=dx; originy+=dy; } public void recenter(int x, int y) { translate(displaywidth/2-x, displayheight/2-y); } public boolean approachcenter(int x, int y) { boolean retval; if (y0) { int packed=CellList[n/2]; int plotx=getPlotX(packed); int ploty=getPlotY(packed); recenter(plotx, ploty); } } public void zoom(int incr) { int x=(displaywidth/2-originx)/cellsize; int y=(displayheight/2-originy)/cellsize; cellsize+=incr; recenter(x*cellsize+originx, y*cellsize+originy); } public void updateStatusLine(Graphics g) { g.setColor(background); g.drawString(statusLine,0,displayheight+15); if (loading!=null) { statusLine="Loading: " + loading; } else { statusLine="Generations: " + generations + " Cells: " + n; } g.setColor(foreground); g.drawString(statusLine,0,displayheight+15); } void resizeIfNeeded(int cellcount) { int tmp[]; int i; if (cellcount>maxcells) { int newsize=2*cellcount; tmp=new int[newsize]; for (i=0; i>5)&0x1fff)-(1<<12))*cellsize+originx; } int getPlotY(int packed) { return ((packed>>18)-(1<<12))*cellsize+originy; } void plotCell(int packed, Graphics g) { int plotx=getPlotX(packed); int ploty=getPlotY(packed); if (plotx > 3 && plotx < displaywidth-3-cellsize && ploty > 3 && ploty < displayheight-3-cellsize ) { int boxsize=cellsize-((cellsize>3)?1:0); g.fillRect(plotx, ploty, boxsize, boxsize); } } public void paintAll(Graphics g) { g.clearRect(0,0,displaywidth, displayheight+statusheight); g.setColor(deadcell); g.fillRect(0,0,displaywidth, displayheight); g.setColor(border); g.drawRect(0,0,displaywidth-1, displayheight-1); g.setColor(livecell); for (int i=0; idisplayheight/h) cellsize= displayheight/h; if (cellsize<1) cellsize=1; originx= (displaywidth-w*cellsize)/2-cellsize/2; originy= (displayheight-h*cellsize)/2-cellsize/2; int[] pixels = new int[w * h]; PixelGrabber pg = new PixelGrabber(img, 0, 0, w, h, pixels, 0, w); try { pg.grabPixels(); } catch (InterruptedException e) { // System.err.println("interrupted waiting for pixels!"); return false; } int i,j; int pix0= pixels[0]; int pix1= -1; int count1= 0; for (i=0; i w*h-count1) { pix1=pix0; count1=w*h-count1; } resizeIfNeeded(count1); n=0; for (i=0; i")); add(new Button("Recenter")); add(patfield=new TextField(patname,8)); LifeList=null; } public void start() { if (killme==null) { killme=new Thread(this); killme.start(); } } public void stop() { killme=null; } public boolean mouseDown(Event ev, int x, int y) { if (LifeList.approachcenter(x,y)) { LifeList.paintAll(getGraphics()); } return true; } public boolean action(Event ev, Object arg) { boolean acted=true; boolean damage=true; if (ev.target instanceof Button) { String label=(String)arg; if (label.equals("Stop")) { pausebutton.setLabel("Start"); generating=false; } else if (label.equals("Start")) { pausebutton.setLabel("Stop"); generating=true; } else if (label.equals("Step")) { stepsleft=1; if (generating) { pausebutton.setLabel("Start"); generating=false; } damage=false; } else if (label.equals("Recenter")) { LifeList.findPattern(); } else if (label.equals("<")) { LifeList.zoom(-1); if (LifeList.cellsize<=1) zoomout.disable(); } else if (label.equals(">")) { LifeList.zoom(1); if (LifeList.cellsize>=2) zoomout.enable(); } else acted=false; } else if (ev.target==patfield) { stop(); LifeList=null; zoomout.enable(); start(); } else acted=false; if (acted && damage) LifeList.paintAll(getGraphics()); return acted; } static String makeGifName(String patname) { int i=patname.indexOf("."); String base=(i<0)?patname:patname.substring(0,i); return base.concat(".gif"); } void loadNew(String patname) { Image img=getImage(getCodeBase(), makeGifName(patname)); LifeList.loading(patname); LifeList.paintAll(getGraphics()); while(killme!=null && !LifeList.loadLifePattern(img, this)) { try {Thread.sleep(200);} catch (InterruptedException e) {} } if (LifeList.cellsize<=1) zoomout.disable(); LifeList.loading(null); LifeList.paintAll(getGraphics()); } public void run() { Graphics g=getGraphics(); if (LifeList==null) { LifeList = new generator(); LifeList.setColors(getBackground(), Color.black, Color.white); LifeList.setCellColors(Color.white, Color.blue); LifeList.setScroll(scrollfraction); LifeList.setDisplaySize(size().width, size().height); loadNew(patfield.getText()); } while (killme != null) { try {Thread.sleep(speed);} catch (InterruptedException e) {} repaint(); } killme=null; } public void paint(Graphics g) { LifeList.paintAll(g); } public void update(Graphics g) { if (generating || stepsleft-- > 0) { LifeList.generate(g); LifeList.updateStatusLine(g); } } }