click on cells to toggle while 2d automaton stopped
[cellular-automaton.git] / 2d.js
diff --git a/2d.js b/2d.js
index cac53ea..f0e5f1e 100644 (file)
--- a/2d.js
+++ b/2d.js
@@ -1,25 +1,13 @@
 $(document).ready(function(){
     
-    var cells = 20;
-    var generations = 10;
-
-    var state = {
-        '000' : '0',
-        '001' : '0',
-        '010' : '0',
-        '011' : '1',
-        '100' : '0',
-        '101' : '1',
-        '110' : '1',
-        '111' : '0',
-    }
-
-    var canvas = document.getElementById('canvas')
+    var canvas = $('#2d-automaton')[0];
     var c = canvas.getContext('2d');
 
-    var cellWidth = Math.floor(canvas.width / cells);
-    var cellHeight = Math.floor(canvas.height / generations);
-    var generation = 0;
+    var rows = 50;
+    var columns = 50;
+
+    var cellWidth = canvas.width / rows;
+    var cellHeight = canvas.height / columns;
 
     function cell(x, y, h, l) {
         this.x = x;
@@ -28,7 +16,7 @@ $(document).ready(function(){
         this.l = l;
         this.state = 0;
         this.kill = function() {
-            c.fillStyle = "rgb(200,0,0)";
+            c.fillStyle = "rgb(255,255,255)";
             c.fillRect(this.x, this.y, this.h, this.l);
             this.state = 0;
         }
@@ -37,36 +25,113 @@ $(document).ready(function(){
             c.fillRect(this.x, this.y, this.h, this.l);
             this.state = 1;
         }
+        this.toggle = function() {
+            this.state ? this.kill() : this.revive();
+        }
     }
 
-    function populate_world() {
-        var world = [];
-        var x = 0;
-        var y = 0;
-        for (var i = 0; i < cells; i++) {
-            world.push(new cell(x, y, cellWidth, cellHeight));
-            x += cellWidth;
-            Math.random() > .5 ? world[i].revive() : world[i].kill();
+    function universe() {
+        this.population = [];
+        this.generation = 0;
+
+        for (var i = 0; i < rows; i++) {
+            var world = [];
+            var x = 0;
+            var y = i * cellHeight;
+            for (var ii = 0; ii < columns; ii++) {
+                world.push(new cell(x, y, cellWidth, cellHeight));
+                x += cellWidth;
+                Math.random() > .5 ? world[ii].revive() : world[ii].kill();
+            }
+            this.population.push(world);
+        }
+
+        this.highlight = function() {
+            for (var i = 0; i < rows; i++) {
+                for (var ii = 0; ii < columns; ii++) {
+                    if (this.population[i][ii].state == 1) {
+                        this.population[i][ii].highlight();
+                    }
+                }
+            }
+        }
+
+        this.redraw = function() {
+            for (var i = 0; i < rows; i++) {
+                for (var ii = 0; ii < columns; ii++) {
+                    if (this.population[i][ii].state == 1) {
+                        this.population[i][ii].redraw();
+                    }
+                }
+            }
         }
-        return world;
     }
 
-    function generate() {
-        generation += 1;
-        var x = 0;
-        var y = generation * cellHeight;
-        var s = '0' + world.map(function(c) { return c.state }).join('') + '0';
-        world = [];
-        for (var i = 0; i < cells; i++) {
-            world.push(new cell(x, y, cellWidth, cellHeight));
-            x += cellWidth;
-            state[s.substr(i, 3)] == 1 ? world[i].revive() : world[i].kill();
+    function tick(automaton) {
+        automaton.generation += 1;
+        var universe = automaton.population;
+        var newUniverse = [];
+        for (var i = 0; i < universe.length; i++) {
+            newUniverse[i] = [];
+            for (var ii = 0; ii < universe[i].length; ii++) {
+                var neighbors = (universe[i][ii+1] ? universe[i][ii+1].state : 0) +
+                                (universe[i][ii-1] ? universe[i][ii-1].state : 0) +
+                                (universe[i+1] ? 
+                                    (universe[i+1][ii] ? universe[i+1][ii].state : 0) +
+                                    (universe[i+1][ii+1] ? universe[i+1][ii+1].state : 0) +
+                                    (universe[i+1][ii-1] ? universe[i+1][ii-1].state : 0)
+                                    : 0) +
+                                (universe[i-1] ? 
+                                    (universe[i-1][ii] ? universe[i-1][ii].state : 0) +
+                                    (universe[i-1][ii-1] ? universe[i-1][ii-1].state : 0) +
+                                    (universe[i-1][ii+1] ? universe[i-1][ii+1].state : 0)
+                                    : 0);
+                universe[i][ii].neighbors = neighbors;
+                if (universe[i][ii].state == 1) {
+                    if (neighbors < 2 || neighbors > 3) {
+                        newUniverse[i][ii] = 0;
+                    } else { 
+                        newUniverse[i][ii] = 1;
+                    }
+                } else {
+                    newUniverse[i][ii] = (neighbors == 3 ? 1 : 0);
+                }
+            }
         }
-        //if (generation == generations) { clearInterval(tick_id) }
+        for (var i in newUniverse) {
+            for (var ii in newUniverse[i]) {
+                newUniverse[i][ii] ? universe[i][ii].revive() : universe[i][ii].kill();
+            }
+        }
+        $('#generation')[0].innerHTML = automaton.generation;
     }
 
-    var world = populate_world();
-    while (generations) { generate(); generations-- }
-    //var tick_id = setInterval(generate, 100);
+    var automaton = new universe;
+    var tickID = 0;
+    var running = 0;
+
+    $('#controls #start-automaton').click(function(e){
+        tickID = setInterval(function(){tick(automaton)}, 100);
+        $('#controls #start-automaton').hide();
+        $('#controls #stop-automaton').show();
+        running = 1;
+    });
+
+    $('#controls #stop-automaton').click(function(e){
+        if (running) clearInterval(tickID);
+        $('#controls #stop-automaton').hide();
+        $('#controls #start-automaton').show();
+        running = 0;
+    });
+
+    $('#2d-automaton').click(function(e) {
+        if (!running) {
+            var x = e.pageX - $('#2d-automaton').offset().left;
+            var y = e.pageY - $('#2d-automaton').offset().top;
+            var row = Math.floor(y / cellHeight);
+            var column = Math.floor(x / cellWidth);
+            automaton.population[row][column].toggle();
+        }
+    });
 
 });