3D Conway's Game of Life in Panda3D (with source code)

This is a project I have wanted to implement for several years, but never found the time to do it. Here I present a 3D version of the classic cellular automaton devised by the mathematician John Conway in 1970.

Source repo: GitHub - rayanalysis/3D-Conway-Game-of-Life: A game engine implementation of 3D Conway's Game of Life in Python with Panda3D

Compute Shader Update
For the adventurous, you can check out an alternative implementation I made using a compute shader to calculate and update the grid positions. This allows significantly larger grid sizes to be represented live, and much faster calculation for smaller grid sizes. The implementation works by passing numpy texture arrays (which encode the 3D grid representation) back and forth between the program and the GPU with RAM images. The next major performance improvement will likely come by representing the cubes with a geometry shader, as the bottleneck now seems to be actually rendering the 3D grid. Implementation here: 3D-Conway-Game-of-Life/compute_shader_experimental at main ยท rayanalysis/3D-Conway-Game-of-Life ยท GitHub

Video of the game in action:

This video demonstrates the deterministic starting grid configuration. By default, the program will begin with a probabilistic starting grid.

As you may well know, the Game of Life can produce surprisingly complex emergent phenomenon from simple rules.

My 3D implementation of the game runs the grid update calculation in a separate thread in order to provide closer to realtime visualization. Still, the updates are slow compared to the 2D representation. I believe that my implementation could run for a very long time, however, so theoretically I imagine that all the emergent behavior you might expect could occur eventually if you ran it long enough.

You may assign whatever grid size you like, though for practical purposes, any grid size over about 25 will tend to be slow on current gen personal computers.

Why did I do it in 3D? Well, 3D is cooler than 2D, and besides that, 3D cellular automata are kind of hot in computer science these days. Myself and some others believe that studying these automata could provide insights into such things as how molecular biology emerged from simple components. I believe this is the first such example of the 3D version of the Game of Life implemented in Panda3D, at least publicly.

Hope you find the program interesting! Iโ€™d be thrilled to see any follow up experiments, or even PRs if you think of something cool to add.

Evolution of a grid with 5,832,000 possible cube positions (generated with the compute shader version):

  1. 3,632 cubes

  2. 44,819 cubes

  3. 264,042 cubes

2 Likes

Those last three screenshots are quite impressive! :slight_smile:

Thanks! That particular version of the program does crash for me right around a quarter million cubes displayed โ€“ however, I imagine that a geometry shader in concert with the compute shader could perhaps take it a bit further and improve performance.

I would like to find some starting configuration that could produce, for instance, true 3D gliders with repeatability. Glider (Conway's Life) - Wikipedia

Because this implementation operates in a higher dimension than the 2D game, there are a greater number of configuration states possible. So maybe, we could discover some even more complex emergent phenomenon. Conversely, it will probably be more difficult to discover them initially.

1 Like

09/17/23 RLE code string support update:

RLE string inputs are now supported via the self.rle_to_bin_list(rle_string) function. This provides your RLE code pattern as a 2D slice for initializing the 3D grid. Ensure that your grid size (self.size) is larger than your minimum pattern bounds. The 60P5H2V0 spaceship representation string is provided by default.

In practical terms, this functionality opens up this 3D expansion of the Game of Life to the vast space of well-studied patterns such as 60P5H2V0 already represented by their 2D RLE codes such as โ€œ4bo23bo$3bobo21bobo$3bobo21bobo$b3ob2o19b2ob3o$o31bo$b3ob2o19b2ob3o$3b
ob2o19b2obo9$12bo7bo$10b2ob2o3b2ob2o$13b2o3b2o$15bobo$8bo4bobobobo4bo$
7b3o5bobo5b3o$7bo5bobobobo5bo$9bo2bo2bobo2bo2bo$9b2o3b2ob2o3b2o$7bo7bo
bo7bo$7bo6b2ob2o6bo!โ€ which would simply need a โ€œ$โ€ added to it to declare the code sequence termination. So the final code would be given like:

        rle_string = '''
    4bo23bo$3bobo21bobo$3bobo21bobo$b3ob2o19b2ob3o$o31bo$b3ob2o19b2ob3o$3b
ob2o19b2obo9$12bo7bo$10b2ob2o3b2ob2o$13b2o3b2o$15bobo$8bo4bobobobo4bo$
7b3o5bobo5b3o$7bo5bobobobo5bo$9bo2bo2bobo2bo2bo$9b2o3b2ob2o3b2o$7bo7bo
bo7bo$7bo6b2ob2o6bo!$'''

Screenshot from compute_shader_experimental (3d_conway_compute_shader.py) showing the 60P5H2V0 spaceship representation initial configuration:

Naturally, this is the most straightforward way to implement existing RLE codes, however, the 3D heuristics are fundamentally different from the standard 2D game. That caveat delineated, this most naive extension of existing RLE codes has produced some pretty fascinating life patterns already from my experiments with it.

2 Likes