John Conway's Game of Life animated using Javascript and displayed using SVG. This document can be viewed using Firefox 1.5, Opera 9 and Microsoft Internet Explorer 6.0 (MSIE6) with the Adobe SVG Viewer 3.03 (ASV).
Notes
When you press a shape button, the shape is always added in a random location in the display in the next update. Don't add too many shapes too quickly or they will clobber each other!
The rules implemented in this demonstration is known as Life 2333 in Carter Bays' notation. A life cell remains alive in the next cycle it has >=2 or <=3 neighbours (the first two digits). A dead cell comes to life it has >=3 or <=3 neighbours (the second two digits).
References
There's plenty of references for the Conway's Game of Life on the Web. Here are the one I used for developing this page.
A. K. Dewdney, The Armchair Universe, 1988, W. H. Freeman and Company.
The display is generated using a Javascript loop that adds as many lines as required, then each cell is displayed by modifying the line's stroke-dasharray attribute. This method avoids creating an object in the DOM for each cell. I found Kevin Lindsey's tip in the Yahoo! svg-developers mailing list.
Also in the Yahoo! svg-developers mailing list, thanks to Martin Honnen's explanation on how to obtain the ASV's document object, I can programmatically create lines in Javascript.
The window.setTimeout("update()", 1) statement is required to allow Firefox to update the display before the next cycle. Without this statement, Firefox doesn't display this page at all.
The memory required should be roughly constant because I try to avoid allocating and deallocating resources after initialization. The same two arrays (cells and cells2) are used for holding the current and next state of the simulation.
Performance Improvement Notes
Initially, this simulation ran so slowly that I added a simple frames per second (fps) meter to measure its speed. This gave me a baseline of 2-3 fps.
If updating cells in updateCells() takes zero time to execute, the performance would be about 30 fps, so that function is the obvious one to improve.
If redrawing cells in SVG in the cells2Display() function takes zero time, performance would only improve by 1 fps, so updating the DOM is not a big performance issue.
Most the time is spent in updateCells() calling the liveOrDead() function to decide if a cell is live or dead in the next cycle.
I split liveOrDead() into two, one to deal with the borders (the original liveOrDead()) and a simpler one to deal with the interior with no bounds checking (liveOrDeadNoBoundsCheck()). That split didn't lead to any performance improvement. What was surprising was that I got a big improvement in performance, achieving 6-7 fps, only after I unrolled the nested loops in liveOrDeadNoBoundsCheck().
There's another slight improvement of 1 fps by using a temporary variable to reference an inner array. That is, I replaced for(c){…cells[r][c]…} with row=cells[r]; for(c){…row[c]…}
I did some simple performance tests with different browsers on an Asus M6R Pentium M 1.7 GHz notebook running Windows XP SP2 and summarized the results in the table below. The Memory number is read from the Mem Usage column of the Windows Task Manager.
Category
Firefox
Opera
MSIE + ASV
FPS
8-9
6-7
5-6
Memory
22-23
15-16
19-20
Obviously, your mileage will vary!
I thought of replacing the Javascript Array with String to improve performance, but I found that it would have required additonal code to manipulate strings like arrays. For example, it is not possible to change an element in a string like this: s[r][c] = "X".