#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# Specific neighbourhoods in the Game of Life

edited June 2017

tl;dr : I reset the variable to store the neighbours in everytime I checked a new neighbour.

I recently found processing and thought the Game of Life would be an easy first project. But when I tried going from neighbourCount only, to saving neighbours in order - in an Array - I stopped getting neighbourCounts bigger than one.

I know it is not needed to store the specific configuration of neighbours to make the Game of Life work, but I want to expand on the idea once I get this working. Why am I not getting the right neighbourCount? I know it's a lot, but I put in as many comments as possible to make it easier on the eyes.

``````int interval = 1000;                         // time between iterations
int lastRecordedTime = 0;                    // timer

int cellSize = 5;                            // size of one Cell
int counterLocal;                            // variable for storing neighbourCount
int [] neighbourhood = {0,0,0,0,0,0,0,0};    // Array for storing neighbourhood configuration
int [][] cells;                              // 2D Cells Array
int [][] cellsBuffer;                        // 2D Buffer Array to work on while leaving cells[][] unharmed

float prob = 30;                             // probability of Cell being alive at setup

color alive = color(0, 0, 0);                // Alive color = black
color dead = color(255, 255, 255);           // Dead color = white

void setup() {
size (200, 200);
cells = new int [width/cellSize][height/cellSize];
cellsBuffer = new int [width/cellSize][height/cellSize];
stroke(48);
noSmooth();

for ( int x = 0; x < width/cellSize; x++) {                // Randomize cells[][]
for ( int y = 0; y < height/cellSize; y++) {
float state = random(100);
if (state > prob) {
state = 0;
} else {
state = 1;
}
cells[x][y] = int(state);
}
}
background(0);
} // end of setup()

void draw() {                                                // Loop through every cell in cells[][] and draw them according to their state
for ( int x = 0; x < width/cellSize; x++) {
for ( int y = 0; y < height/cellSize; y++) {
if (cells[x][y] == 1) {
fill(alive);
} else {
fill (dead);
}
rect (x*cellSize, y*cellSize, cellSize, cellSize);
}
}
if (millis() - lastRecordedTime > interval) {
iteration();
lastRecordedTime = millis();
}
} // end of draw()

void iteration() {
for (int x = 0; x < width/cellSize; x++) {                                       // copy cells Array to cellsBuffer
for (int y = 0; y < height/cellSize; y++) {
cellsBuffer[x][y] = cells[x][y];
}
}

for (int x = 0; x < width/cellSize; x++) {                                       // go through every cell
for (int y = 0; y < height/cellSize; y++) {

String neighbourCode = "0,0,0,0,0,0,0,0";                                    // string used to encode neighbour positions

for (int xx=x-1; xx<=x+1; xx++) {                                            // go through all neighbours of current Cell
for (int yy=y-1; yy<=y+1; yy++) {

if (((xx>=0)&&(xx<width/cellSize))&&((yy>=0)&&(yy<height/cellSize))) {   // Make sure you are not out of bounds
//if (!((xx==x)&&(yy==y))) {                                           // Make sure to to check against self (not needed)

int[] codeArray = int(split(neighbourCode, ","));                    // Split string into Array

if ((x - xx == 1) && (y - yy == 1)) {           //top left           //1. Check which neighbour you are (if, else if, else if...)
if (cellsBuffer[xx][yy] == 1){
codeArray[0] = 1;                                                  //2. if alive, set codeArray at corresponding index to 1
}
}

else if ((x - xx == 0) && (y - yy == 1)) {      //top mid
if (cellsBuffer[xx][yy] == 1){
codeArray[1] = 1;
}
}

else if ((x - xx == -1) && (y - yy == 1)) {     //top right
if (cellsBuffer[xx][yy] == 1){
codeArray[2] = 1;
}
}

else if ((x - xx == 1) && (y - yy == 0)) {       //mid left
if (cellsBuffer[xx][yy] == 1){
codeArray[3] = 1;
}
}

else if ((x - xx == -1) && (y - yy == 0)) {      //mid right
if (cellsBuffer[xx][yy] == 1){
codeArray[4] = 1;
}
}

else if ((x - xx == 1) && (y - yy == -1)) {      //bot left
if (cellsBuffer[xx][yy] == 1){
codeArray[5] = 1;
}
}

else if ((x - xx == 0) && (y - yy == -1)) {       //bot mid
if (cellsBuffer[xx][yy] == 1){
codeArray[6] = 1;
}
}

else if ((x - xx == -1) && (y - yy == -1)) {      //bot right
if (cellsBuffer[xx][yy] == 1){
codeArray[7] = 1;
}
}                                                 // finished making codeArray

for (int n = 0; n < codeArray.length; n++) {      // copy codeArray to public Array
neighbourhood[n] = codeArray[n];
}

int neighbourCount = 0;
for (int neighbourIndex = 0; neighbourIndex < codeArray.length; neighbourIndex++) {      // Converting neighbourCode to neighbourCount
if (codeArray[neighbourIndex] == 1) {
neighbourCount = neighbourCount + 1;
}
}                                                // end of Conversion
counterLocal = neighbourCount;                   // copy neighbourCount to public int

//} // end of self check (not needed)
} // end of out of Bounds check
} // end of for (yy++) loop
} // end of for (xx++) loop

if (cellsBuffer[x][y] == 1) {                                              // applying ruleset for the game of life and writing to cells Array
if (counterLocal < 2 || counterLocal > 3) {
cells [x][y] = 0;
}
} else {
if (counterLocal == 3) {
cells[x][y] = 1;
}
}

} // end of for (y++) loop
} // end of for (x++) loop
}  //end of iteration ()
``````

If you're still reading this, you are my hero.

Tagged:

## Answers

• To make clear what I want: Check neighbourhood of each cell and record them, so their "location data" (relative to current cell) gets preserved until I am done applying the rules.

Right now I am trying to save them in codeArray[]

I calculate the index at which I save the neighbour in codeArray by comparing x and y of the current cell to xx and yy (those are the coordinates of the neighbour I am currently looking at).

So for a cell which has the 4 neighbours in the cardinal directions alive and every other is dead I would hope the array looks like this: {0,1,0,1,1,0,1,0} Also this was heavily inspired by: https://processing.org/examples/gameoflife.html

• I haven't reviewed this code yet, but a common error in GoL implementations is to alter the matrix as you read it. You can't do that. You need to take one pass and calculate all the neighbor counts, then a second pass and update the matrix. Are you already doing this, or are you editing cells while you are reading / updating your cellBuffer? That's a first guess at a problem to check for.

• edited June 2017

Have not programmed much last month and a half but this idea sparked my interest to get back into it.
From the PM's it sounds like what you're trying to do could also be described as an "elementary CA", but with 9 bits and in 2D rather than just the 3 bits ontop?

This is a bit crude and might contain misstakes but a start

EDIT: changed code as I found the rule corresponding to game of life

``````import java.math.*;
BigInteger rule;
int swap,xyz=200;
boolean[][][] fields = new boolean[2][xyz][xyz];

boolean closerThan(int len, int x0, int y0, int x1, int y1){
float delx = x0-x1;
float dely = y0-y1;
delx*=delx;
dely*=dely;
len*=len;
return delx+dely < len;
}

void clear() {
for(int b=0;b<2;b++){
for (int x=0;x < xyz; x++) {
for (int y = 0; y < xyz; y++) {
fields[b][x][y] = false;
}}}
}
void setup(){
size(200,200);
clear();
loadPixels();
rule = new BigInteger("95269658970504075026401947768164943776577911284651056525821775275694548745963441068740035536685992072438984633721408802547302109256447217920");
}
boolean algorithm(int d,int x0,int y0) {

if ( closerThan(10,x0,y0,mouseX,mouseY) ){
return true;
}
int up=(y0+xyz-1)%xyz;
int down=(y0+xyz+1)%xyz;
boolean n0=fields[swap][(x0+xyz-1)%xyz][up];
boolean n1=fields[swap][x0][up];
boolean n2=fields[swap][(x0+1)%xyz][up];
boolean n3=fields[swap][(x0+xyz-1)%xyz][y0];
boolean n4=fields[swap][x0][y0];
boolean n5=fields[swap][(x0+1)%xyz][y0];
boolean n6=fields[swap][(x0+xyz-1)%xyz][down];
boolean n7=fields[swap][x0][down];
boolean n8=fields[swap][(x0+1)%xyz][down];
int state = (n0?1:0)+
(n1?2:0)+
(n2?4:0)+
(n3?8:0)+
(n4?16:0)+
(n5?32:0)+
(n6?64:0)+
(n7?128:0)+
(n8?256:0);
return rule.shiftRight(state).testBit(1);
}
void draw() {
for (int y=0;y<xyz;y++){
for (int x=0;x<xyz;x++){
fields[(swap+1)%2][x][y]=algorithm(0,x,y);
pixels[x+xyz*y]=algorithm(0,x,y)?#000000:#ffffff;}}
if(swap==0){swap=1; updatePixels();}else{swap=0;}
fill(0);rect(0,xyz,xyz,16);fill(255);
}
``````
• edited June 2017

@jeremydouglass

Ok let me work through this out loud to understand it myself:

1. Copy cells[][] to cellsBuffer[][] (lines 63ff)

2. Loop through cellsBuffer[][]

• for each cell in Buffer: (lines 72 - 80)

• count its neighbours, (lines 83 - 146)
• update cells[][] according to rules (lines 157 - 165)
• go to next cell in Buffer.

Saving my cells[][] is the only time I write to cellsBuffer[][], so I am never reading and writing to the same array in the same step. I strongly suspect the problem is with the actual counting of the neighbours and/or the int array I try to save them to... (lines 75+83ff)

Thanks for the suggestion

@prince_polka

Thank you so much for taking your time, there's a lot in there to check out. I've had trouble with the pixels array on my first try, so I started over and replaced it with my own 2D array, after watching The Coding Train videos on CA...

Also: you can do return in a void method? (your code line39) Or only in setup?

• no problem,
A method has to return whatever type it starts with, void means nothing and thus can't return anything.

• made a sketch to find the rule for game of life for the 9-bit automata above

``````import java.math.*;
BigInteger gol;
int n;
boolean alive;
void setup(){
gol= new BigInteger("0");
for (int i=0; i<512; i++){
n=0;
for (int j=0; j<9; j++){
if (j!=4){
n+= (i >> j)&1;
}
}
alive=((i>>4)&1)==1;
if ( alive && n==2 ){ gol = gol.setBit(i+1); }
if(n==3){ gol = gol.setBit(i+1);

}
}
println(gol.toString());
}
``````

turns out to be

95269658970504075026401947768164943776577911284651056525821775275694548745963441068740035536685992072438984633721408802547302109256447217920

• @prince_polka That's nice, but I think you are skipping every other frame, even though you're doing the calculations correctly, from just looking at the pictures.

To be honest, your calculations are a bit beyond me.. I sort of understand how you get neighbours positions with the booleans. I don't quite get

``````int state = (n0?1:0)+
(n1?2:0)+
(n2?4:0)+
(n3?8:0)+
(n4?16:0)+
(n5?32:0)+
(n6?64:0)+
(n7?128:0)+
(n8?256:0);
return rule.shiftRight(state).testBit(1)
``````

I know you're converting from boolean to int, but not how the state interacts with the BigInteger

(oh and a small thing: int swap,xyz=200; is that the same as int swap=200; int xyz=200; ?

• Answer ✓

I haven't noticed the skipping and I'm aware my code is cryptic.

(oh and a small thing: int swap,xyz=200; is that the same as int swap=200; int xyz=200; ?
no its swap undeclared, xyz = 200, if you wanted to set both to 200 you could do

``````int swap,xyz;
swap=xyz=200;
``````

the one i call swap I at least intended to swap back and forth each frame between 0-1 to get a ping pong buffering kind of thing going.
xyz is the dimensions

one thing I'm wondering is if you have any ideas for an interface to enter alternative rules into the system?

• edited June 2017

Ah it's starting to make sense now. At least I got a lot of material now to continue my google adventures. No need to apologize for cryptic code, have you looked at my hot mess?

Still have too many ideas for interfaces, I'll have to familiarize myself with libraries first I think, making buttons and stuff seems like a hassle. One thing I'm sure I want is a feature to make a random ruleset with a variable ratio of (configurations that result in death)/(configurations that result in life) Quickly swap out rulesets maybe

I'm also interested in comparing different methods of doing the same thing; so your code really helps a lot, thanks. wrapping my head around arrays, lists, bit manipulation.. honestly I'm just having fun with it.

• edited June 2017 Answer ✓

@HolyMoley -- yes, from your description it sounds like you are using the buffer correctly. My first guess was probably wrong.

when I tried going from neighbourCount only, to saving neighbours in order - in an Array - I stopped getting neighbourCounts bigger than one.

These are the lines that jump out at me:

``````else if ((x - xx == 0) && (y - yy == 1))
``````

...should that `else` be there in `else if`?

Those elses make it look like you are only registering one neighbor per neighborhood, then skipping to the end of the conditions. You probably want to test each condition independently with a set of eight simple `if` blocks...?

• edited June 2017

I fixed the else ifs to ifs and I finally figured it out... It would help if I don't make a new Array every time I go to the next neighbour. Took the initialization of the Array out of the xx,yy loop and it works now. What a silly mistake... This is my interation() now:

``````for (int x = 0; x < width/cellSize; x++) {  // Go through every cell
for (int y = 0; y < height/cellSize; y++) {

boolean codeArray[] = {false, false, false, false, false, false, false, false}; // Make array to store neighbourhood

for (int xx=x-1; xx<=x+1; xx++) {  // Go through all neighbours of current Cell
for (int yy=y-1; yy<=y+1; yy++) {
construct Array in here.

}
}
}
}
``````
• Why do you need the 3x3 array?

• edited June 2017

@koogs converting the 9 states of current cell in the 2D cells[][] Array, that define the neighbourhood, into a 1D codeArray[]. Compare codeArray to rules and update cells accordingly. I could make the rules use a 2D array as well, but then I'd have to convert down eventually..I think.

• edited June 2017

I know you're converting from boolean to int, but not how the state interacts with the BigInteger

looking at the n'th bit, counted "backwards".

Maybe the rightshift is superfluos to do this,

rule.shiftRight(state).testBit(1) rule.testBit(state)

havent tested it yet

`return rule.testBit(state+1);` works

have you looked at my hot mess?

I actuallt barelly looked at your actual code to be honest.

• I think your original code is redundant because you run xx and yy over all neighbours but then you check with if which neighbour you are looking at.

I got rid of the for xx and for yy loop and put the neighbour check in a sub function `checkNeighbours` :

``````int interval = 1000;                         // time between iterations
int lastRecordedTime = 0;                    // timer

int cellSize = 5;                            // size of one Cell
int counterLocal;                            // variable for storing neighbourCount
int [] neighbourhood = {0, 0, 0, 0, 0, 0, 0, 0};    // Array for storing neighbourhood configuration
int [][] cells;                              // 2D Cells Array
int [][] cellsBuffer;                        // 2D Buffer Array to work on while leaving cells[][] unharmed

float prob = 30;                             // probability of Cell being alive at setup

color alive = color(0, 0, 0);                // Alive color = black
color dead = color(255, 255, 255);           // Dead color = white

void setup() {
size (200, 200);
cells = new int [width/cellSize][height/cellSize];
cellsBuffer = new int [width/cellSize][height/cellSize];
stroke(48);
noSmooth();

// Randomize cells[][]
for ( int x = 0; x < width/cellSize; x++) {
for ( int y = 0; y < height/cellSize; y++) {
float state = random(100);
if (state > prob) {
state = 0;
} else {
state = 1;
}
cells[x][y] = int(state);
}
}
background(0);
} // end of setup()

void draw() {
// Loop through every cell in cells[][] and draw them according to their state
for ( int x = 0; x < width/cellSize; x++) {
for ( int y = 0; y < height/cellSize; y++) {
if (cells[x][y] == 1) {
fill(alive);
} else {
fill (dead);
}
rect (x*cellSize, y*cellSize, cellSize, cellSize);
}
}
if (millis() - lastRecordedTime > interval) {
iteration();
lastRecordedTime = millis();
}
} // end of draw()

// ---------------------------------------------------------------------

void iteration() {
//
for (int x = 0; x < width/cellSize; x++) {   // copy cells Array to cellsBuffer
for (int y = 0; y < height/cellSize; y++) {
cellsBuffer[x][y] = cells[x][y];
}
}

for (int x = 0; x < width/cellSize; x++) {        // go through every cell
for (int y = 0; y < height/cellSize; y++) {

String neighbourCode = "0,0,0,0,0,0,0,0";     // string used to encode neighbour positions

// go through all neighbours of current Cell
int[] codeArray  = checkNeighbours(x, y);

for (int n = 0; n < codeArray.length; n++) {      // copy codeArray to public Array
neighbourhood[n] = codeArray[n];
}

int neighbourCount = 0;
// Converting neighbourCode to neighbourCount
for (int neighbourIndex = 0; neighbourIndex < codeArray.length; neighbourIndex++) {
if (codeArray[neighbourIndex] == 1) {
neighbourCount = neighbourCount + 1;
}
}                  // end of Conversion
counterLocal = neighbourCount;     // copy neighbourCount to public int

// applying ruleset for the game of life and writing to cells Array
if (cellsBuffer[x][y] == 1) {
if (counterLocal < 2 || counterLocal > 3) {
cells [x][y] = 0;
}
} else {
if (counterLocal == 3) {
cells[x][y] = 1;
}
}
} // end of for (y++) loop
} // end of for (x++) loop
}  //end of function iteration ()

int[] checkNeighbours(int x, int y) {

// Make array to store neighbourhood
// int codeArray[] = {false, false, false, false, false, false, false, false};
int codeArray[] = {0, 0, 0, 0, 0, 0, 0, 0}; // Make array to store neighbourhood

// if alive, set codeArray at corresponding index to 1

final int top=y-1;
final int mid=y;
final int bottom=y+1;

final int left=x-1;
final int midX=x;
final int right=x+1;

if (isValid(left, top) && cellsBuffer[left][top] == 1) {   // top left
codeArray[0] = 1;
}

if (isValid(midX, top) &&cellsBuffer[midX][top] == 1) {     //top mid
codeArray[1] = 1;
}

if (isValid(right, top) && cellsBuffer[right][top] == 1) {     //top right
codeArray[2] = 1;
}

if (isValid(left, mid) && cellsBuffer[left][mid] == 1) {    //mid left
codeArray[3] = 1;
}

if (isValid(right, mid) && cellsBuffer[right][mid] == 1) {    //mid right
codeArray[4] = 1;
}

if (isValid(left, bottom) && cellsBuffer[left][bottom] == 1) { //bottom left
codeArray[5] = 1;
}

if (isValid(midX, bottom) && cellsBuffer[midX][bottom] == 1) {  //bottom mid
codeArray[6] = 1;
}

if (isValid(right, bottom) && cellsBuffer[right][bottom] == 1) {    //bottom right
codeArray[7] = 1;
}
// finished making codeArray

return codeArray;
}

boolean isValid(int x, int y) {

// Make sure you are not out of bounds

if ( (x>=0) &&
(x<width/cellSize) &&
(y>=0) &&
(y<height/cellSize) )
return true; // correct

// otherwise return false
return false;
}

//
``````
• ``````import java.math.*;
BigInteger rule;
int swap,n;
int xyz=40;
int cellsize=5;
boolean alive;
boolean[][][] fields = new boolean[2][xyz][xyz];
boolean codeArray[] = new boolean[9];
boolean closerThan(int len, int x0, int y0, int x1, int y1){
float delx = x0-x1;
float dely = y0-y1;
delx*=delx;
dely*=dely;
len*=len;
return delx+dely < len;
}

void setgol(){
rule= new BigInteger("0");
for (int i=0; i<512; i++){
n=0;
for (int j=0; j<9; j++){
if (j!=4){
n+= (i >> j)&1;
}
}
alive=((i>>4)&1)==1;
if ( alive && n==2 ){ rule = rule.setBit(i); }
if(n==3){ rule = rule.setBit(i);
}
}
}

void clear() {
for(int b=0;b<2;b++){
for (int x=0;x < xyz; x++) {
for (int y = 0; y < xyz; y++) {
fields[b][x][y] = false;
}}}
}
void setup(){
size(200,200);
clear();
loadPixels();
setgol();
frameRate(15);
}
boolean judge(int d,int x0,int y0) {
if ( closerThan(10,x0,y0,mouseX/cellsize,mouseY/cellsize) ){ return true; }
int up=(y0+xyz-1)%xyz;
int down=(y0+xyz+1)%xyz;
codeArray[0]=fields[swap][(x0+xyz-1)%xyz][up];
codeArray[1]=fields[swap][x0][up];
codeArray[2]=fields[swap][(x0+1)%xyz][up];
codeArray[3]=fields[swap][(x0+xyz-1)%xyz][y0];
codeArray[4]=fields[swap][x0][y0];
codeArray[5]=fields[swap][(x0+1)%xyz][y0];
codeArray[6]=fields[swap][(x0+xyz-1)%xyz][down];
codeArray[7]=fields[swap][x0][down];
codeArray[8]=fields[swap][(x0+1)%xyz][down];
int state = 0;
for (int i=0; i<9; i++){
state+= codeArray[i]?(int(pow(2,i))):0;
}
return rule.testBit(state);
}
void draw() {
for (int y=0;y<xyz;y++){
for (int x=0;x<xyz;x++){
fields[(swap+1)%2][x][y]=judge(0,x,y);
fill(judge(0,x,y)?#000000:#ffffff);
rect(x*cellsize,y*cellsize,cellsize,cellsize);
}}
//pixels[x+xyz*y]=judge(0,x,y)?#000000:#ffffff;}}
if(swap==0){
swap=1;
//updatePixels();
} else {swap=0;}
}
``````
• edited June 2017 Answer ✓

Compare codeArray to rules and update cells accordingly.

so the rules are more than just a count?

my optimisation for this whole bit (original post)

``````          if ((x - xx == 1) && (y - yy == 1)) {           //top left           //1. Check which neighbour you are (if, else if, else if...)
if (cellsBuffer[xx][yy] == 1){
codeArray[0] = 1;                                                  //2. if alive, set codeArray at corresponding index to 1
}
}
else if ((x - xx == 0) && (y - yy == 1)) {      //top mid
if (cellsBuffer[xx][yy] == 1){
codeArray[1] = 1;
}
}
else if ((x - xx == -1) && (y - yy == 1)) {     //top right
if (cellsBuffer[xx][yy] == 1){
codeArray[2] = 1;
}
}
else if ((x - xx == 1) && (y - yy == 0)) {       //mid left
if (cellsBuffer[xx][yy] == 1){
codeArray[3] = 1;
}
}
else if ((x - xx == -1) && (y - yy == 0)) {      //mid right
if (cellsBuffer[xx][yy] == 1){
codeArray[4] = 1;
}
}
else if ((x - xx == 1) && (y - yy == -1)) {      //bot left
if (cellsBuffer[xx][yy] == 1){
codeArray[5] = 1;
}
}
else if ((x - xx == 0) && (y - yy == -1)) {       //bot mid
if (cellsBuffer[xx][yy] == 1){
codeArray[6] = 1;
}
}
else if ((x - xx == -1) && (y - yy == -1)) {      //bot right
if (cellsBuffer[xx][yy] == 1){
codeArray[7] = 1;
}
}                                                 // finished making codeArray
``````

would be to just to use a counter. set it to 0 outside the xx, yy loops and then the loop body becomes

``````codeArray[count] = cellsBuffer[xx][yy];
count++;
``````

that's it. no need for all those checks. the loops in lines 77 and 78 iterate over the neighbours in the correct order, you just need to remember the position. (this array also includes the cell being checked, whereas you omit it)

but if i was coding the classic game of life i'd do it completely differently - loop over all the current pixels and iff the pixel is set then increment all the neighbours in the array for the next step. much fewer comparisons, no overlaps. and you only have to process the black squares.

• edited June 2017

@koogs Yes! I was scratching my head for so long, thinking about how to convert the relative coordinates to an index, when I could've just counted them.

This will be perfect for the new and clean project, where I use objects and make things pretty. Thanks a lot!

• edited June 2017

implemented interface to change rules
EDIT: and grayscale

``````import java.math.*;
BigInteger rule;
golbutton[] button = new golbutton[512];
PImage viewport;

boolean codeArray[] = new boolean[9];
int box=10;
int swap;
int xyz=100;
boolean[][][] fields = new boolean[2][xyz][xyz];
int cellsize=5;
color store;

boolean mpa,click; //mouse variable
int[] stay ={2};
int[] born = {3};
void setgol(int[]stay,int[]born){
boolean alive;
int n;
rule= new BigInteger("0");
for (int i=0; i<512; i++){
n=0;
alive=((i>>4)&1)==1;
for (int j=0; j<9; j++){
if (j!=4){
n+= (i >> j)&1;
}
}
for (int j=0;j<stay.length;j++){
if ( alive && n==stay[j] ) {
rule = rule.setBit(i);
break;
}
}
for (int j=0;j<born.length;j++){
if (n==born[j] ) {
rule = rule.setBit(i);
break;
}
}
}
}
boolean judge(int d,int midx,int midy) {
if ( closerThan(10,midx,midy,mouseX/cellsize,mouseY/cellsize) ){
return true;
}
int up=(midy+xyz-1)%xyz;
int down=(midy+xyz+1)%xyz;
int left=(midx+xyz-1)%xyz;
int right=(midx+1)%xyz;
boolean[][]f = fields[swap];
codeArray[0]=f[left][up];
codeArray[1]=f[midx][up];
codeArray[2]=f[right][up];
codeArray[3]=f[left][midy];
codeArray[4]=f[midx][midy];
codeArray[5]=f[right][midy];
codeArray[6]=f[left][down];
codeArray[7]=f[midx][down];
codeArray[8]=f[right][down];
int state = 0;
for (int i=0; i<9; i++){
state+= codeArray[i]?(int(pow(2,i))):0;
}
store = color(255-state/2);
return rule.testBit(state);
}

boolean closerThan(int len, int x0, int y0, int x1, int y1){
float delx = x0-x1;
float dely = y0-y1;
delx*=delx;
dely*=dely;
len*=len;
return delx+dely < len;
}

color fillcolor;
class golbutton{
int posx;
int posy;
int i;
int margin=box/2;
int size=box*4;
boolean alive;
boolean mob;
golbutton(int I){
i=I;
alive=rule.testBit(i);
posx=500+box/2+(i%32)*size;
posy=box/2+(i/32)*size;
}
void toggle(){
alive=!alive;
if(alive){ rule = rule.setBit(i);}
else     { rule = rule.clearBit(i);}
}
void show(){
mob = (mouseX>posx && mouseX<posx+size && mouseY>posy && mouseY<posy+size);
if(mob && click){toggle();}
fillcolor=alive? #00ff00 : #ff0000;
if(mob){fillcolor=#ffff00;}
fill(fillcolor);
rect(posx,posy,box*4,box*4);

for (int j=0; j<9; j++){
fillcolor = ((i>>j)&1) == 1 ? #000000 : #ffffff;
fill(fillcolor);
rect(posx+margin+(j%3)*box,posy+margin+j/3*box,box,box);
}
}
}

void setup(){
size(1790,650);
noStroke();
noSmooth();
viewport = createImage(xyz,xyz,ARGB);
viewport.loadPixels();
loadPixels();
setgol(stay,born);
for (int i=0; i<512; i++){
button[i] = new golbutton(i);
}
}
void draw(){
click=(!mpa && mousePressed);
for (int i=0; i<512; i++){
button[i].show();
}
for (int y=0;y<xyz;y++){
for (int x=0;x<xyz;x++){
fields[(swap+1)%2][x][y]=judge(0,x,y);
//fill(judge(0,x,y)?#000000:#ffffff);
viewport.pixels[x+y*xyz]=store;
//rect(x*cellsize,y*cellsize,cellsize,cellsize);
}}
viewport.updatePixels();
image(viewport,0,0,xyz*cellsize,xyz*cellsize);
if(swap==0){swap=1;}else{swap=0;}
mpa=mousePressed;
}
``````
Sign In or Register to comment.