computational craft

totalistic code 976

rosettaposter

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.

two-dimensional cellular automaton starting from a random condition; totalistic code 976. Music from lovebrain's new album "color out of sound".
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

976Grasshopper

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; }