totalistic code 976
Rosetta
This is an example of the same algorithm written in three different coding environments (Rhinoscript, Grasshopper .NET & Processing). It's useful to examine the dirent structures & syntax.
![]() |
Behavior of a two dimensional cellular automaton starting from a random initial condition. At each step, each cell looks at the total number of black cells in the 9-cell neighborhood consisting of the cell itself and the 8 cells adjacent to it (including diagonals). If the total is less than 4, then the cell becomes white on the next step, while if the total is greater than 6, it becomes black. If the total is exactly 5, then the cell becomes white, and if the total is exactly 4, then it becomes black. (The rule has totalistic code 976.) The video below shows that on a large scale, the rule leads to regions of black and white whose boundaries behave in a seemingly smooth and continuous way.
Stephen Wolfram, New Kind of Science p.336
Code in RhinoScript
Option Explicit
'Script written by Ezio Blasetti
'Script copyrighted by algorithmicdesign.net
'Script version Friday, September 25, 2009 4:44:59 PM
Call Main()
Sub Main()
Dim intLength : intLength = 50
Dim intWidth : intWidth = 50
Dim intGen : intGen = 15
ReDim arrSize(intLength,intWidth)
Dim arrValues : arrValues = randomizeArray01(arrSize)
Dim arrMeshes : arrMeshes = render(arrValues)
Dim i,j
For i=0 To intGen
arrValues = applyTotalistic976(arrValues)
'arrValues = applyGOL(arrValues)
Call update(arrMeshes, arrValues)
Next
'Call DeleteObjects2dArray(arrMeshes)
End Sub
Function applyTotalistic976(arrValues)
applyTotalistic976 = Null
Dim i,j
Dim arrNewValues : arrNewValues = arrValues
For j=0 To Ubound(arrValues,2)
For i=0 To Ubound(arrValues,1)
Dim dblSum : dblSum = sumNeighbors(arrValues, i, j, True)
If dblSum < 4 Then
arrNewValues(i,j) = 0
ElseIf dblSum > 5 Then
arrNewValues(i,j) = 1
ElseIf dblSum = 5 Then
arrNewValues(i,j) = 0
ElseIf dblSum = 4 Then
arrNewValues(i,j) = 1
Else
arrNewValues(i,j) = arrValues(i,j)
End If
Next
Next
applyTotalistic976 = arrnewValues
End Function
Function applyGOL(arrValues)
applyGOL = Null
Dim i,j
Dim arrNewValues : arrNewValues = arrValues
For j=0 To Ubound(arrValues,2)
For i=0 To Ubound(arrValues,1)
Dim dblSum : dblSum = sumNeighbors(arrValues, i, j, False)
If arrValues(i,j) = 1 Then
If dblSum < 2 Then
arrNewValues(i,j) = 0
ElseIf dblSum > 3 Then
arrNewValues(i,j) = 0
Else
arrNewValues(i,j) = 1
End If
Else
If dblSum = 3 Then
arrNewValues(i,j) = 1
Else
arrNewValues(i,j) = 0
End If
End If
Next
Next
applyGOL = arrNewValues
End Function
Function sumNeighbors(arrValues, i, j, blnSelf)
sumNeighbors = Null
Dim iplus1 : iplus1 = i+1
Dim iminus1 : iminus1 = i-1
If i = 0 Then iminus1 = Ubound(arrValues,1)
If i = Ubound(arrValues,1) Then iplus1 = 0
Dim jplus1 : jplus1 = j+1
Dim jminus1 : jminus1 = j-1
If j = 0 Then jminus1 = Ubound(arrValues,2)
If j = Ubound(arrValues,2) Then jplus1 = 0
Dim dblSum : dblSum = 0
dblSum = dblSum + arrValues(iminus1,jminus1)
dblSum = dblSum + arrValues(i ,jminus1)
dblSum = dblSum + arrValues(iplus1 ,jminus1)
dblSum = dblSum + arrValues(iminus1,j )
If blnSelf Then dblSum = dblSum + arrValues(i,j)
dblSum = dblSum + arrValues(iplus1 ,j )
dblSum = dblSum + arrValues(iminus1,jplus1 )
dblSum = dblSum + arrValues(i ,jplus1 )
dblSum = dblSum + arrValues(iplus1 ,jplus1 )
sumNeighbors = dblSum
End Function
Function render(arrValues)
render = Null
Call Rhino.EnableRedraw(vbFalse)
Dim arrMeshes : arrMeshes = arrValues
Dim i,j
For j=0 To Ubound(arrValues,2)
For i=0 To Ubound(arrValues,1)
Dim arrPoints : arrPoints = array(array((i-0.5),(Ubound(arrValues,2)-j-0.5),0),_
array((i+0.5),(Ubound(arrValues,2)-j-0.5),0),_
array((i+0.5),(Ubound(arrValues,2)-j+0.5),0),_
array((i-0.5),(Ubound(arrValues,2)-j+0.5),0))
arrMeshes(i,j) = addMeshQuad(arrPoints)
Call colorMeshQuad(arrMeshes(i,j), arrValues(i,j))
Next
Next
Call Rhino.EnableRedraw(vbTrue)
render = arrMeshes
End Function
Function update(arrMeshes, arrValues)
update = Null
Call Rhino.EnableRedraw(vbFalse)
Dim i,j
For j=0 To Ubound(arrValues,2)
For i=0 To Ubound(arrValues,1)
Call colorMeshQuad(arrMeshes(i,j), arrValues(i,j))
Next
Next
Call Rhino.EnableRedraw(vbTrue)
update = arrMeshes
End Function
Sub DeleteObjects2dArray(arrObjects)
Call Rhino.EnableRedraw(vbFalse)
Dim i,j
For j=0 To Ubound(arrObjects,2)
For i=0 To Ubound(arrObjects,1)
Call Rhino.DeleteObject(arrObjects(i,j))
Next
Next
Call Rhino.EnableRedraw(vbTrue)
End Sub
Function randomizeArray(arr)
randomizeArray = Null
Dim i,j
For j=0 To Ubound(arr,2)
For i=0 To Ubound(arr,1)
arr(i,j) = rnd
Next
Next
randomizeArray = arr
End Function
Function randomizeArray01(arr)
randomizeArray01 = Null
Dim i,j
For j=0 To Ubound(arr,2)
For i=0 To Ubound(arr,1)
If rnd-0.5<0 Then
arr(i,j) = 0
Else
arr(i,j) = 1
End If
Next
Next
randomizeArray01 = arr
End Function
Function addMeshQuad(arrPoints)
Dim arrFaceVertices(0)
arrFaceVertices(0) = Array(0,1,2,3)
addMeshQuad = Rhino.AddMesh (arrPoints, arrFaceVertices)
End Function
Sub colorMeshQuad(strMesh, dblValue)
Dim lngColor : lngColor = RGB(255-dblValue*255,255-dblValue*255,255-dblValue*255)
Call Rhino.ObjectColor(strMesh, lngColor)
Dim intMaterialIndex : intMaterialIndex = Rhino.AddMaterialToObject (strMesh)
Call Rhino.MaterialColor(intMaterialIndex, lngColor)
End Sub
Definition in Grasshopper
Inside the main .net node:
Sub RunScript(ByVal InitStates As List(Of Integer), ByVal xNum As Integer, ByVal yNum As Integer, ByVal Gen As Double)
'Generate 2D grid of points
Dim Grid(,) As On3dPoint
ReDim Grid(xNum, yNum)
GenerateGrid(xNum, yNum, Grid)
'Generate 2D grid of state
Dim SGrid(xNum, yNum) As Integer
GenerateStateGrid(InitStates, xNum, yNum, SGrid)
'Get state at the defined generation
Dim i,j As Integer
For i = 0 To Gen
NewGeneration(SGrid, xNum, yNum)
Next
'Make a list of points
Dim LPoints As New List(Of On3dPoint )
For i = 0 To xNum - 1
For j = 0 To yNum - 1
LPoints.Add(Grid(i, j))
Next
Next
'Make a list of states
Dim LStates As New List(Of Integer )
For i = 0 To xNum - 1
For j = 0 To yNum - 1
LStates.Add(SGrid(i, j))
Next
Next
'print(InitStates.Count())
outPoints = LPoints
outStates = LStates
End Sub
#Region "Additional methods and Type declarations"
Sub GenerateGrid(ByVal xNum As Integer, ByVal yNum As Integer, ByRef Grid As On3dPoint(,))
Dim i,j As Integer
Dim x,y As Integer
x = 0
y = 0
'Create rows
For i = 0 To xNum - 1
y = 0
For j = 0 To yNum - 1
Dim pt As New On3dPoint(i, j, 0)
Grid(x, y) = pt
y = y + 1
Next
x = x + 1
Next
End Sub
Sub GenerateStateGrid(ByVal State As List(Of Integer), ByVal xNum As Integer, ByVal yNum As Integer, ByRef SGrid As Integer(,))
Dim i,j As Integer
Dim x,y As Integer
x = 0
y = 0
'Create rows
For i = 0 To State.Count() - 1 Step yNum
y = 0
For j = i To i + yNum - 1
Dim st As Integer
st = State(j)
SGrid(x, y) = st
y = y + 1
Next
x = x + 1
Next
End Sub
Sub NewGeneration(ByRef States As Integer(,), ByVal xNum As Integer, ByVal yNum As Integer)
Dim i,j As Integer
Dim intLCount As Integer
Dim SNewGrid(xNum, yNum) As Integer
For i = 0 To xNum - 1
For j = 0 To yNum - 1
SNewGrid(i, j) = States(i, j)
Next
Next
Dim prev_i, next_i, prev_j, next_j As Integer
For i = 0 To (xNum - 1)
'First index
If i = 0 Then
'Take last index
prev_i = xNum - 1
Else
prev_i = i - 1
End If
'Last index
If i = xNum - 1 Then
'Take first index
next_i = 0
Else
next_i = i + 1
End If
For j = 0 To (yNum - 1)
If j = 0 Then
prev_j = yNum - 1
Else
prev_j = j - 1
End If
'Check next col
If j = yNum - 1 Then
next_j = 0
Else
next_j = j + 1
End If
'Zero the living cells count
intLCount = 0
'Count number of live neighbors (8 of them)
intLCount = intLCount + States(next_i, j)
intLCount = intLCount + States(prev_i, j)
intLCount = intLCount + States(i, next_j)
intLCount = intLCount + States(i, prev_j)
intLCount = intLCount + States(i, j)
intLCount = intLCount + States(next_i, next_j)
intLCount = intLCount + States(next_i, prev_j)
intLCount = intLCount + States(prev_i, next_j)
intLCount = intLCount + States(prev_i, prev_j)
If intLCount < 4 Then
SNewGrid(i, j) = 0
ElseIf intLCount > 5 Then
SNewGrid(i, j) = 1
ElseIf intLCount = 5 Then
SNewGrid(i, j) = 0
ElseIf intLCount = 4 Then
SNewGrid(i, j) = 1
Else
SNewGrid(i, j) = States(i, j)
End If
Next
Next
States = SnewGrid
End Sub
Code in Processing
//Script written by Ezio Blasetti for algorithmicdesign.net
import processing.opengl.*;
int intHeightCells = 100;
int intWidthCells = 190;
int height = 500;
int width = 950;
float [][] arrValues = new float [intWidthCells][intHeightCells];
void setup ()
{
size(width,height, OPENGL);
randomizeArray(arrValues);
}
void draw(){
render(arrValues);
arrValues = applyTotalisitc976(arrValues);
//arrValues = applyGOL(arrValues);
}
float [][] randomizeArray(float arr[][]){
for (int j=0; j5){
arrNewValues[i][j] = 1;
}
else if(dblSum==5){
arrNewValues[i][j] = 0;
}
else if(dblSum==4){
arrNewValues[i][j] = 1;
}
else{
arrNewValues[i][j] = arrValues[i][j];
}
}
}
return arrNewValues;
}
float [][] applyGOL(float arrValues[][]){
float [][] arrNewValues = new float [intWidthCells][intHeightCells];
for (int j=0; j3){
arrNewValues[i][j] = 0;
}
else {
arrNewValues[i][j] = 1;
}
}
else {
if (dblSum==3) {
arrNewValues[i][j] = 1;
}
else {
arrNewValues[i][j] = 0;
}
}
}
}
return arrNewValues;
}
float sumNeighbors(float arrValues[][], int i, int j, boolean blnSelf){
int iplus1 = i + 1;
int iminus1 = i - 1;
if (i == 0) {
iminus1 = intWidthCells-1;
}
if (i == intWidthCells-1) {
iplus1 = 0;
}
int jplus1 = j + 1 ;
int jminus1 = j - 1 ;
if (j == 0) {
jminus1 = intHeightCells-1;
}
if (j == intHeightCells-1) {
jplus1 = 0;
}
float dblSum = 0;
dblSum = dblSum + arrValues[iminus1][jminus1];
dblSum = dblSum + arrValues[i ][jminus1];
dblSum = dblSum + arrValues[iplus1 ][jminus1];
dblSum = dblSum + arrValues[iminus1][j ];
if (blnSelf) {
dblSum = dblSum + arrValues[i ][j ];
}
dblSum = dblSum + arrValues[iplus1 ][j ];
dblSum = dblSum + arrValues[iminus1][jplus1 ];
dblSum = dblSum + arrValues[i ][jplus1 ];
dblSum = dblSum + arrValues[iplus1 ][jplus1 ];
return dblSum;
}

