Game of Life. Universal

by DaniilTutubalin
Convolution filter + paletteMap = super fast Game of Life simulation.
♥3 | Line 66 | Modified 2012-09-11 02:29:21 | MIT License
play

ActionScript3 source code

/**
 * Copyright DaniilTutubalin ( http://wonderfl.net/user/DaniilTutubalin )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/fiMy
 */

/* Game of Life by Daniil Tutubalin

The idea was invented partially by me, partially by other people.
Quasimondo  http://www.quasimondo.com/archives/000680.php 
was the first who got an idea to use paletteMap for Game of Life.
My initial idea was to use threshold method, 
but it required to be called twice and it was much less adapting for different rules. 
Using paletteMap is one line shorter and more adapting.

So, this code allows you to experiment with different rules of Game of Life
*/

package {
    import flash.geom.Point;
    import flash.filters.ConvolutionFilter;
    import flash.display.Bitmap;
    import flash.events.Event;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    public class Life extends Sprite {
        
        
        // Rules: neighbors to born / neighbors to survive                
        // You may experiment with it
        
        //* Classic rules: cell borns if and only if 3 neighbors are nearby, cell survive if 2 or 3 neighbors
        private const RULES:String = "3/23"; /**/        
        
        /* Walled Cities - best with density = 17%
        private const RULES:String = "45678/2345" /**/        
        
        /* Maze generation
        private const RULES:String = "23/12345" /**/
        
        /* Space travellers
        private const RULES:String = "B368/S245" /**/
        
        // More rules can be found here: http://en.wikipedia.org/wiki/Life-like_cellular_automaton
                
        // Density of initial noise in percents
        // You may change it
        private const DENSITY:Number = 17;
                       
        // Convolution filter. 
        // 1 for every neighbor, 9 for cell itself
        // so empty cell result in 0..8 depending on number of neighbors
        // live cell result in 9..17
        private const LIFE_FILTER:ConvolutionFilter = new ConvolutionFilter(3, 3, [1,1,1,1,9,1,1,1,1], 255, 0, true, false, 0, 1);
                
        private const POINT_ZERO:Point = new Point();
        private const EMPTY_ARRAY:Array = [];
        
        private var gameField:BitmapData;
        private var bitmap:Bitmap;
        private var palette:Array;
        
        public function Life() {            
            if (stage) {
                init();
            } else {
                addEventListener(Event.ADDED_TO_STAGE, init);
            }
        }
        
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            // create field
            gameField = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
            
            // make some noise
            var colorMin:int;
            var colorMax:int;
            if (DENSITY <= 50) {
                colorMin = 0;
                colorMax = 5.1 * DENSITY;                  
            } else {
                colorMin = 5.1 * (DENSITY-50)
                colorMax = 255;
            }
            gameField.noise(int(Math.random()*int.MAX_VALUE),colorMin,colorMax,1,true);
            
            // put on stage            
            bitmap = new Bitmap(gameField);
            addChild(bitmap);
            
            // init palette array
            palette = [];
            var rules:Array = RULES.split("/");
            var born:String = rules[0];
            var survive:String = rules[1];            
            
            // 0..8 - to burn
            for (var i:int = 0; i<9; i++) {
                if (born.indexOf(String(i)) != -1) {
                    palette.push(0xFFFFFF);
                } else {
                    palette.push(0x000000);
                }
            }
            // 9..17 - to survive
            for (i = 0; i<9; i++) {
                if (survive.indexOf(String(i)) != -1) {
                    palette.push(0xFFFFFF);
                } else {
                    palette.push(0x000000);
                }
            }
            
            addEventListener(Event.ENTER_FRAME, run);
        }

        private function run(e:Event = null):void {
            gameField.lock();
            gameField.applyFilter(gameField,gameField.rect, POINT_ZERO, LIFE_FILTER);
            gameField.paletteMap(gameField,gameField.rect, POINT_ZERO, palette, [], []);
            gameField.unlock();
        }

    }
}

Forked