Reaction and Diffusion Code
in
Programming Questions
•
3 months ago
I am trying to make a multi-state CA similar to the image above. The code was shared on the website but when I copied and pasted it I only got coloured points, not coloured cells, as in the image above. Can someone help me figure out what is going on? The code is long, but I can't tell what parts are actually doing something and what's fat. Thanks
- 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];
- }
- }
- }
- }
- //////////////////////////////
- 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 amounts, 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 * 10,j * 10, pixelColor);
- fill(pixelColor);
- }
- }
- }
- 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);
- }
- }
- }
- }
1