// The classic "Conway's Life" a-life app. // implementation by Dan Efran in SWiSHmax/SWiSHscript // the very clever idea of using convolution filters // to do the math came from 5etdemi.com, aka Patrick Mineault, // who in turn credits Andre Michelle with suggesting the scheme // All I did was implement it as they suggested. // the code below assumes that certain objects already exist // on the stage. /* These functions must be called by GUI button clicks: timerStop timerGo stepTime dishFavorite dishFavorite2 randomCells */ onLoad () { // start of main execution flow timerID = 0; timerRunning = false; timerSpeed = 100; createDish(); dishFavorite2(); displayDish(); } function timerTick() { tickDish(); } function stepTime() { timerStop(); tickDish(); } function timerGo() { if (!timerRunning) { timerID = setInterval(timerTick, timerSpeed); timerRunning = true; } } function timerStop() { if (timerRunning) { timerRunning = false; clearInterval(timerID); } } function createDish() { lifeIsRunning = false; rndSeed = 1; BMD_t = flash.display.BitmapData; lifeData = new BMD_t(100,100,true,0x000000FF); neighborData = new BMD_t(100,100,true,0x000000FF); visData = new BMD_t(100,100,true,0x000000FF); nextData = new BMD_t(100,100,true,0x000000FF); dataRect = new flash.geom.Rectangle(0,0,100,100); dataPoint = new flash.geom.Point(0,0); dish.attachBitmap(visData,1); var arr:Array = [1,1,1,1,10,1,1,1,1]; neighborCountFilter = new flash.filters.ConvolutionFilter(3,3, arr, 1,0,true,true, 0x000000,0xFF); randomCells(); clearDish(); } function randomCells() { rndSeed++; lifeData.noise(rndSeed, 0,1,1|2|4,true); displayDish(); } function displayDish() { var cellColor = 0xFFAAAAAA; visData.copyPixels(lifeData, dataRect, dataPoint); visData.threshold(visData, dataRect, dataPoint, ">", 0, cellColor,0x000000FF,false); } function clearDish() { lifeData.colorTransform(dataRect, new flash.geom.ColorTransform(0,0,0,0, 0,0,0,0xff) ); } function dishFavorite() { clearDish(); lifeData.setPixel(50,50, 0xFF000001 ); lifeData.setPixel(50,51, 0xFF000001 ); lifeData.setPixel(50,52, 0xFF000001 ); lifeData.setPixel(51,50, 0xFF000001 ); lifeData.setPixel(52,51, 0xFF000001 ); displayDish(); } function dishFavorite2() { clearDish(); lifeData.setPixel(50,50, 0xFF000001 ); lifeData.setPixel(50,51, 0xFF000001 ); lifeData.setPixel(50,49, 0xFF000001 ); lifeData.setPixel(49,50, 0xFF000001 ); lifeData.setPixel(51,49, 0xFF000001 ); displayDish(); } function tickDish() { // here's where we do the clever bit, // doing parallelized (wrt ActionScript) computation // on many 2D array elements via image filters // neighbors count 1 each; self is 10 neighborData.applyFilter(lifeData, dataRect, dataPoint, neighborCountFilter); // threshold lets us test the result for life rules // conway 2333 life: nextData.colorTransform(dataRect, new flash.geom.ColorTransform(0,0,0,0, 0,0,0,255) ); nextData.threshold(neighborData, dataRect, dataPoint, "==", 12, 0xFF000001, 0x000000FF,false); nextData.threshold(neighborData, dataRect, dataPoint, "==", 13, 0xFF000001, 0x000000FF,false); nextData.threshold(neighborData, dataRect, dataPoint, "==", 3, 0xFF000001, 0x000000FF,false); // make that the new generation clearDish(); lifeData.threshold(nextData, dataRect, dataPoint, ">",0, 0xFF000001, 0x000000FF,false); displayDish(); } function toggleCell(xx, yy) { var temp:Number = lifeData.getPixel32(xx,yy) & 0x000000FF; lifeData.setPixel32(xx, yy, (1-temp) | 0xFF000000); displayDish(); }