0

I've setup a 3D cellular automata script that seems to work. But I don't see any of the typical CA patterns like gliders or blinkers etc.

My guess is that its something to do with the order of how I am checking neighbors. Or how I've set up the basic grid.

Here is a short animation from Unity.

Here's the grid setup part:

 private void CreateGrid(int y)
{
    GameObject CellObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
    CellObject.transform.localScale = cubeScale;

    int i = 0;

    for (int z = 0; z < GridWidth; z++)
    {
        for (int x = 0; x < GridHeight; x++)
        {
            CellGrid[i] = Instantiate(CellObject, new Vector3(x, y, z), transform.rotation) as GameObject;
            CellGrid[i].GetComponent<MeshRenderer>().material = WhiteMat;
            i++;
        }
    }

}

Here's the Game of Life part:

 private void GameOfLife()
{

    for (int i=0; i < CellGrid.Length; i++)
    {
        int count = 0;

        var CellMat = CellGrid[i].GetComponent<Renderer>().sharedMaterial;

        //8 Neighbour Names : NeighNW, NeighN, NeighNE, NeighW, NeighE, NeighSW, NeighS, NeighSE,


        //CHECK 1 of 8 NeighSW 
        if ((i-(GridWidth +1) >= 0 )&& i- (GridWidth + 1) <= CellGrid.Length)
        {
            var NeighSW = CellGrid[i- (GridWidth + 1)];
            var NeighSWmat = NeighSW.GetComponent<Renderer>().sharedMaterial;
            if (NeighSWmat != null)
            {
                if (NeighSWmat != WhiteMat)
                {
                    count++;
                    //Debug.Log("Black Material found, SW of cell"+ i);
                }
                else if (NeighSWmat == WhiteMat)
                {
                    //Debug.Log("White Cell SW of " + i);
                }
                else if (NeighSWmat == TetrinoMat1)
                {
                    count++;
                }
            }
            else
            {
                Debug.Log("Material Error with Cell no." + i);
            }
        }
        else
        {
            //Debug.Log("no NeighSW cell " + i);
        }   //End of NeighSW Check


        //CHECK 2 of 8 NeighS
        if ((i - (GridWidth) >= 0) && i - (GridWidth) <= CellGrid.Length)
        {
            var NeighS = CellGrid[i - (GridWidth)];
            var NeighSmat = NeighS.GetComponent<Renderer>().sharedMaterial;
            if (NeighSmat != null)
            {
                if (NeighSmat != WhiteMat)
                {
                    count++;
                    //Debug.Log("Black Material found, S of cell"+ i);
                }
                else if (NeighSmat == WhiteMat)
                {
                    //Debug.Log("White Cell S of " + i);
                }
                else if (NeighSmat == TetrinoMat1)
                {
                    count++;
                }

            }
            else
            {
                Debug.Log("Material Error with Cell no." + i);
            }
        }
        else
        {
            //Debug.Log("no NeighS cell " + i);
        }   //End of NeighS Check


        //CHECK 3 of 8 NeighSE
        if ((i - (GridWidth - 1) >= 0) && i - (GridWidth - 1) <= CellGrid.Length)
        {
            var NeighSE = CellGrid[i - (GridWidth - 1)];
            var NeighSEmat = NeighSE.GetComponent<Renderer>().sharedMaterial;
            if (NeighSEmat != null)
            {
                if (NeighSEmat != WhiteMat)
                {
                    count++;
                    //Debug.Log("Black Material found, SE of cell"+ i);
                }
                else if (NeighSEmat == WhiteMat)
                {
                    //Debug.Log("White Cell SE of " + i);
                }
                else if (NeighSEmat == TetrinoMat1)
                {
                    count++;
                }

            }
            else
            {
                Debug.Log("Material Error with Cell no." + i);
            }
        }
        else
        {
            //Debug.Log("no NeighSE cell " + i);
        }   //End of NeighSE Check


        //CHECK 4 of 8 NeighE
        if ((i - (GridWidth - 1) >= 0) && i - (GridWidth - 1) <= CellGrid.Length)
        {
            var NeighE = CellGrid[i - (+ 1)];
            var NeighEmat = NeighE.GetComponent<Renderer>().sharedMaterial;
            if (NeighEmat != null)
            {
                if (NeighEmat != WhiteMat)
                {
                    count++;
                    //Debug.Log("Black Material found, E of cell"+ i);
                }
                else if (NeighEmat == WhiteMat)
                {
                    //Debug.Log("White Cell E of " + i);
                }
                else if (NeighEmat == TetrinoMat1)
                {
                    count++;
                }

            }
            else
            {
                Debug.Log("Material Error with Cell no." + i);
            }
        }
        else
        {
            //Debug.Log("no NeighE cell " + i);
        }   //End of NeighE Check


        //CHECK 5 of 8 NeighW
        if ((i - (1) >= 0) && i - (GridWidth - 1) <= CellGrid.Length)
        {
            var NeighW = CellGrid[i - 1];
            var NeighWmat = NeighW.GetComponent<Renderer>().sharedMaterial;
            if (NeighWmat != null)
            {
                if (NeighWmat != WhiteMat)
                {
                    count++;
                    //Debug.Log("Black Material found, W of cell"+ i);
                }
                else if (NeighWmat == WhiteMat)
                {
                    //Debug.Log("White Cell W of " + i);
                }
                else if (NeighWmat == TetrinoMat1)
                {
                    count++;
                }

            }
            else
            {
                Debug.Log("Material Error with Cell no." + i);
            }
        }
        else
        {
            //Debug.Log("no NeighE cell " + i);
        }   //End of NeighW Check

        //CHECK 6 of 8 NeighNW 
        if ((i + (GridWidth - 1) >= 0) && i + (GridWidth - 1) < CellGrid.Length)
        {
            var NeighNW = CellGrid[i + (GridWidth - 1)];
            var NeighNWmat = NeighNW.GetComponent<Renderer>().sharedMaterial;
            if (NeighNWmat != null)
            {
                if (NeighNWmat != WhiteMat)
                {
                    count++;
                    //Debug.Log("Black Material found, NW of cell"+ i);
                }
                else if (NeighNWmat == WhiteMat)
                {
                    //Debug.Log("White Cell NW of " + i);
                }
                else if (NeighNWmat == TetrinoMat1)
                {
                    count++;
                }

            }
            else
            {
                Debug.Log("Material Error with Cell no." + i);
            }
        }
        else
        {
            //Debug.Log("no NeighNW cell " + i);
        }   //End of NeighNW Check


        //CHECK 7 of 8 NeighN
        if ((i + (GridWidth) >= 0) && i + (GridWidth) < CellGrid.Length)
        {
            var NeighN = CellGrid[i + (GridWidth)];
            var NeighNmat = NeighN.GetComponent<Renderer>().sharedMaterial;
            if (NeighNmat != null)
            {
                if (NeighNmat != WhiteMat)
                {
                    count++;
                    //Debug.Log("Black Material found, S of cell"+ i);
                }
                else if (NeighNmat == WhiteMat)
                {
                    //Debug.Log("White Cell S of " + i);
                }
                else if (NeighNmat == TetrinoMat1)
                {
                    count++;
                }

            }
            else
            {
                Debug.Log("Material Error with Cell no." + i);
            }
        }
        else
        {
            //Debug.Log("no NeighN cell " + i);
        }   //End of NeighN Check


        //CHECK 8 of 8 NeighNE
        if ((i + (GridWidth + 1) >= 0) && i + (GridWidth + 1) < CellGrid.Length)
        {
            var NeighNE = CellGrid[i + (GridWidth + 1)];
            var NeighNEmat = NeighNE.GetComponent<Renderer>().sharedMaterial;
            if (NeighNEmat != null)
            {
                if (NeighNEmat != WhiteMat)
                {
                    count++;
                    //Debug.Log("Black Material found, SE of cell"+ i);
                }
                else if (NeighNEmat == WhiteMat)
                {
                    //Debug.Log("White Cell SE of " + i);
                }
                else if (NeighNEmat == TetrinoMat1)
                {
                    count++;
                }

            }
            else
            {
                Debug.Log("Material Error with Cell no." + i);
            }

        }
        else
        {
            //Debug.Log("no NeighNE cell " + i);
        }   //End of NeighNE Check
                                                     
        

        //COUNT TALLY
        //Debug.Log("Cell no." + i + " Neighbour count " + count) ;

        
        //RULE 1 - Any live cell with fewer than two live neighbors dies, as if caused by under-population.
        if ((CellMat != WhiteMat) && (count < 2))
        {
            killCell(i);
        }

        //RULE 2 - Any live cell with two or three live neighbors lives on to the next generation.
        if((CellMat != WhiteMat) && (count >= 2) && (count <=3))
        {
            DoNothing(i);
        }

        //RULE 3 - Any live cell with more than three live neighbors dies, as if by overcrowding.
        if ((CellMat != WhiteMat) && (count > 3))
        {
            killCell(i);
        }

        //RULE 4 - Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
        if ((CellMat == WhiteMat) && (count == 3))
        {
            BirthCell(i);
        }


    }

}

1 Answers1

1

Your code has three flaws. First of all, the first if clause for NeighE and neighW is incorrect. Additionally, NeighE is actually using the west neighbor; change CellGrid[i - (+ 1)] to CellGrid[i + 1].

Finally, by the behavior of the animation you showed, you are implementing the transition itself wrong. In a cellular automaton, all cells change state at the same time, so that if you set a cell to a different state, its neighbors that are processed afterwards don't see the change until after all cells have been processed.

The easiest way to do this is double buffering: you read from a source buffer and write to a destination buffer, then swap them when everything is done. Another possibility that avoids the use of two buffers is having one invisible extra row in the single buffer, starting the pass from the end it's on and writing each cell to the one in the previous row, then shifting the view so that the last row is now the invisible one, and reversing directions in the next step.

Aritz Erkiaga
  • 51
  • 1
  • 6