This shows an early version of my Wu Xing-inspired cellular automata, taking the form of a Reaction-Diffusion model. This isn’t as commented and a little more obscure than the DLA code, but you should be able to copy/paste the code into processing and get a simple reaction/diffusion cellular automata in Processing:

class WuXingCell

##### {

float[] element;

};

int worldScale = 8;

int worldSize = 64;

int mode = 1;

WuXingCell[][] world;

WuXingCell[][] nextWorld;

color[] WuXingColor;

float waterLevel = .25;

int dayBand = 0;

float natLog = 0.36787944118;

float eLog = 2.7182818284;

float growRate = .2;

float destroyRate = .11;

float insultRate = .1;

float growThresh = .1;

float destroyThresh = .2;

float insultThresh = .4;

float[] elementFlow; //how much is moved when it erodes

float[] elementStrength; //when element decides to erode

float[] elementDistScale; //distance from strongest points

float[] elementReactivity;

int dominantElement = 0;

float seaLevel = 0;

int water = 0; //we do this so the code is more readable, also showing the cyclical order

int wood = 1;

int fire = 2;

int earth = 3;

int metal = 4;

int mouseElement = 0;

float[] alchemyAmounts;

float[] alchemyAdditives;

boolean elementPoles = true;

boolean react = false;

void updateWorld()

{

for (int i = 0; i < worldSize; i++)

{

for (int j = 0; j < worldSize; j++)

{

for (int k = 0; k < 5; k++)

{

world[i][j].element[k] = nextWorld[i][j].element[k];

//print(“.”);

}

}

}

}

void ProcessWorld()

{

for (int i = 0; i < worldSize; i++)

{

for (int j = 0; j < worldSize; j++)

{

for (int k = 0; k < 5; k++) //imagine 5 buckets in each cell, we look at them and their neighbors…

{

alchemyAmounts[k] = world[i][j].element[k];

for (int adjI = -1; adjI < 2; adjI++)

{

for (int adjJ = -1; adjJ < 2; adjJ++)

{

alchemyAmounts[k] += (world[LoopVar(i + adjI)][LoopVar(j + adjJ)].element[k]) * (0.125); //0.125 = 1/8th, averaging the 8 adjacent cells

}

}

}

ProcessAlchemy(); //now that we have the amoutns, process what they do…

for (int k = 0; k < 5; k++) //a little bit of hacky averaging, and updating the old board

{

alchemyAmounts[k]/=2;

nextWorld[i][j].element[k] = alchemyAmounts[k];

}

}

}

}

void ProcessAlchemy()

{

float[] newAlchemy = new float[5];

float[] fractionOf = new float[5];

float totalAmount = 0;

for (int k = 0; k < 5; k++)

{

newAlchemy[k] = alchemyAmounts[k];

totalAmount += alchemyAmounts[k];

}

for (int k = 0; k < 5; k++)

{

fractionOf[k] = totalAmount/alchemyAmounts[k];

}

int grandParent, parent, child, grandChild;

for (int k = 0; k < 5; k++) //figure out what elements are “parent”, “child” etc. relative to the one you’re on

{

grandParent = 6;

parent = 6;

child = 6;

grandChild = 6;

if (k == water)

{

grandParent = earth;

parent = metal;

child = wood;

grandChild = fire;

}

if (k == wood)

{

grandParent = metal;

parent = water;

child = fire;

grandChild = earth;

}

if (k == fire)

{

grandParent = water;

parent = wood;

child = earth;

grandChild = metal;

}

if (k == earth)

{

grandParent = wood;

parent = fire;

child = metal;

grandChild = water;

}

if (k == metal)

{

grandParent = fire;

parent = earth;

child = water;

grandChild = wood;

}

elementReactivity[k] = 1;// *= 1.5; //how much do we react the elements (scalar, multply by this amount)

//natLog = .3;

newAlchemy[k] += (alchemyAmounts[parent] * natLog);

newAlchemy[k] -= (alchemyAmounts[child] * natLog);

if (alchemyAmounts[grandParent] > alchemyAmounts[k]) //grandfather destroys…

{

newAlchemy[k] -= (alchemyAmounts[grandParent] * natLog);

}

// else //…or it’s too big and we’re insulted

if (alchemyAmounts[grandChild] > alchemyAmounts[k])// //grandfather destroys…

{

newAlchemy[k] -= (alchemyAmounts[grandParent] * natLog);

}

if ( newAlchemy[k] > 1.0) newAlchemy[k] = 1.0;

if ( newAlchemy[k] < 0.0) newAlchemy[k] = 0.0;

}

for (int k = 0; k < 5; k++)

{

alchemyAmounts[k] = newAlchemy[k];

}

}

void draw()

{

dominantElement += 1;

if (dominantElement >= 5) dominantElement = 0;

ProcessWorld();

ProcessAlchemy();

updateWorld();

background(0);

color pixelColor = color(0,0,0);

float finRed, finGreen, finBlue;

if(keyPressed) {

if (key == ‘0’) {

alchemyAdditives[water] += .1;

//mouseElement = water;

}

if (key == ‘1’) {

alchemyAdditives[wood] += .1;

//mouseElement = wood;

}

if (key == ‘2’) {

alchemyAdditives[fire] += .1;

//mouseElement = fire;

}

if (key == ‘3’) {

alchemyAdditives[earth] += .1;

//mouseElement = earth;

}

if (key == ‘4’) {

alchemyAdditives[metal] += .1;

//mouseElement = metal;

}

if (key == ‘r’) {

for (int k = 0; k < 5; k++)

{

alchemyAmounts[k]= random(0,1.0);

}

}

if (key == ‘e’) {

for (int k = 0; k < 5; k++)

{

alchemyAmounts[k]= 0;

alchemyAdditives[k] = 0;

}

//mouseElement = water;

}

if (key == ‘t’) {

for (int k = 0; k < 5; k++)

{

alchemyAmounts[k] += alchemyAdditives[k];

alchemyAdditives[k] = 0;

}

//mouseElement = water;

}

}

float maxElement = 0;

int theMaxElement = 0;

int numElements = 0;

for (int i = 0; i < worldSize; i++) //do a bunch of comparisons to get colors, but we’re basically looping through the board and drawing

{

for (int j = 0; j < worldSize; j++)

{

finRed = 0;

finGreen = 0;

finBlue = 0;

maxElement = 0;

theMaxElement = 0;

numElements = 0;

for (int k = 0; k < 5; k++)

{

if (world[i][j].element[k] > maxElement)

{

maxElement = world[i][j].element[k];

theMaxElement = k;

}

if (world[i][j].element[k] > 0)

{

numElements++;

}

finRed += (red(WuXingColor[k]) * world[i][j].element[k]);

finGreen += (green(WuXingColor[k]) * world[i][j].element[k]);

finBlue += (blue(WuXingColor[k]) * world[i][j].element[k]);

}

finRed /= numElements;

finGreen /= numElements;

finBlue /= numElements;

if (((world[i][j].element[earth] + world[i][j].element[metal])/2) <= seaLevel)

{

pixelColor = color(0,0,seaLevel);

}

else

{

pixelColor = WuXingColor[theMaxElement];//color(finRed,finGreen,finBlue);

//pixelColor *= world[i][j].element[theMaxElement];

//pixelColor = color(world[i][j].element[3],world[i][j].element[2],0);

switch(theMaxElement)

{

case 0:

pixelColor = color(0,world[i][j].element[0],world[i][j].element[0]);

break;

case 1:

pixelColor = color(0,world[i][j].element[1],0);

break;

case 2:

pixelColor = color(1.0,0,0);

break;

case 3:

pixelColor = color(world[i][j].element[3],world[i][j].element[2],0);

break;

case 4:

pixelColor = color(world[i][j].element[3],world[i][j].element[3],world[i][j].element[2]);

break;

}

pixelColor = color(finRed,finGreen,finBlue);//color(finRed,finGreen,finBlue);

}

if (((world[i][j].element[earth] + world[i][j].element[earth])/2) > seaLevel)

{

//pixelColor = color(0,(world[i][j].element[earth] + world[i][j].element[earth])/2,0);

}

else

{

//pixelColor = color(0,(world[i][j].element[earth] + world[i][j].element[earth])/2,.75);

}

if (((world[i][j].element[earth] + world[i][j].element[metal])/2) <= seaLevel)

{

//pixelColor = color(0,0,seaLevel);

}

else

{

//pixelColor = color(finRed,finGreen,finBlue);

}

// if (elementVision != 5) pixelColor = color(0,world[i][j].element[elementVision],0);

//pixelColor = color(0,world[i][j].element[metal],0);

// pixelColor = color(0,0, world[i][j].element[0] );

//pixelColor = color (world[i][j].element[0],0,0);

//set (i * 2,j * 2,pixelColor);

//set (i * 1,j * 1,pixelColor);

fill(pixelColor);

rect(i * worldScale, j * worldScale, (i * worldScale) + (worldScale – 1), (j * worldScale) + (worldScale – 1));

}

}

}

float Clamp(float tempVar, float low, float high)

{

if (tempVar < low) tempVar = low;

if (tempVar > high) tempVar = high;

return tempVar;

}

int LoopVar(int theVar) //clamps var to make sure we loop, assume error is never more than one or two “off map”

{

if (theVar < 0)

{

theVar += worldSize;

}

if (theVar >= worldSize)

{

theVar -= worldSize;

}

return theVar;

}

void setup()

{

//worldScale = 2;

frameRate(24);

colorMode(RGB, 1.0);

size(worldSize * worldScale,worldSize * worldScale);

world = new WuXingCell[worldSize][worldSize];

nextWorld = new WuXingCell[worldSize][worldSize];

//growRate = .2;

//destroyRate = .2;

//insultRate = .1;

WuXingColor = new color[5];

WuXingColor[water] = color(0,0,1);//water

WuXingColor[wood] = color(0,1,0);//wood

WuXingColor[fire] = color(1,0,0);//fire

WuXingColor[earth] = color(1,1,0);//earth

WuXingColor[metal] = color(1,1,1);//metal

elementFlow = new float[5];

elementStrength = new float[5];

elementDistScale = new float[5];

elementReactivity = new float[5];

alchemyAmounts = new float[5];

alchemyAdditives = new float[5];

for (int k = 0; k < 5; k++)

{

elementFlow[k] = 0;

elementStrength[k] = 0;

elementDistScale[k] = 1;

elementReactivity[k] = 1;

alchemyAmounts[k] = 0.5;//random(0,1.0);

alchemyAdditives[k] = 0;

}

elementFlow[earth] = .05; //earth

elementStrength[earth] = .1;

//elementFlow[metal] = .25; //metal

//elementStrength[metal] = .3;

elementFlow[metal] = .4; //metal

elementStrength[metal] = .5;

elementFlow[fire] = .21;

elementStrength[fire] = .11;

for (int i = 0; i < worldSize; i++)

{

for (int j = 0; j < worldSize; j++)

{

world[i][j] = new WuXingCell();

world[i][j].element = new float[5];

for (int k = 0; k < 5; k++)

{

world[i][j].element[k] = random(.1,.9);//.25 + random(0,.5);//random(0.0,1.0);//.5;

// world[i][j].element[k] = 0.5;

//world[i][j].element[k]/=255;

}

//world[i][j].element[0] = .6;

//world[i][j].element[0] = .2;

nextWorld[i][j] = new WuXingCell();

nextWorld[i][j].element = new float[5];

for (int k = 0; k < 5; k++)

{

nextWorld[i][j].element[k] = 1;//random(0,1);

}

//print(” “);

//print(world[i][j].terraHeight);

}

}

//ProcessHeat();

}

Thanks a lot for posting this, but unfortunately we cannot copy the code for some reason.