0

I am attempting to recreate the neural cellular automaton shown in this video using openGL and c. I am using a simple Game of Life demo shown in minute 7:08 of the video to check if my code works (the filter and and the activation function are also shown in minute 7:08), the problem is that my code is not acting the way it should even though I did everything, we can see this in Frame1 and 2,in Frame1 we can see the glider but once the filter and activation is appled it acts completely differently, the glider should act like in conways game of life but its behaviour follows a seemingly random ruleset.

Frame1: Frame2:

code:

#include <stdio.h>
#include <windows.h>
#include <GL/glut.h>

#define sleep(x) Sleep(1000 * (x))

#define sizeX 10
#define sizeY 10
#define wallSize 40

int frame = 0;

double grid[sizeY][sizeX];
double filter[3][3] = {{1, 1, 1},
                       {1, 9, 1},
                       {1, 1, 1}};
                       

int width = 1000;
int height = 500;

double activation(double x){
    if(x == 3 || x == 11 || x == 12){
        return 1;
    }
    else{
        return 0;
    }
}

void CVFilter(){
    int x,y;
    double cv; //covolved value
    for(y=1;y<sizeY-1;y++){
  for(x=1;x<sizeX-1;x++){
    cv = (grid[y+1][x-1]*filter[0][0]) + (grid[y+1][x]*filter[0][1]) + (grid[y+1][x+1]*filter[2][2])+
         (grid[y][x-1]*filter[1][0]) + (grid[y][x]*filter[1][1]) + (grid[y][x+1]*filter[1][2])+
         (grid[y-1][x-1]*filter[2][0]) + (grid[y-1][x]*filter[2][1]) + (grid[y-1][x+1]*filter[2][2]);
            grid[y][x] = activation(cv);
  }
 }
}

void drawGrid(){
 int x,y;
 double rgb;
 glPointSize(wallSize);
 glBegin(GL_POINTS);
 for(y=0;y<sizeY;y++){
  for(x=0;x<sizeX;x++){
    rgb = grid[y][x];
    glColor3f(rgb,rgb,rgb);
    glVertex2i((x*wallSize),(y*wallSize));
  }
 }
 glEnd();
}

void display(){
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 if(frame == 1){
  CVFilter();
 }
 if(frame == 2){
    sleep(1000);
 }
 //-----------------------Draw----------------------
 drawGrid();
 //-------------------------------------------------
 glutSwapBuffers();
 glutPostRedisplay();
 sleep(3);
 frame++;
}


void init(){
 glClearColor(0.3,0.3,0.3,0);
 gluOrtho2D(0,width,height,0);
}

void main(int argc, char** argv){ 
 grid[5][5] = 1; //Draws the glider
 grid[4][5] = 1; //Draws the glider
 grid[3][5] = 1; //Draws the glider
    grid[5][4] = 1; //Draws the glider
    grid[4][3] = 1; //Draws the glider
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
 glutInitWindowSize(width,height);
 glutCreateWindow("OpenGL");
 init();
 glutDisplayFunc(display);
 glutMainLoop();
}
Saw
  • 115
  • 1
  • 16
  • 5
    Looks like you are trying to do a convolution in place. In other words, `grid` elements you modify are used for other elements within the same step. You probably want to make a copy. – Nelfeal Oct 29 '22 at 15:28
  • 1
    You can avoid copying the whole grid by only storing the cell coordinates that were modified in an array. After the filter has completed, apply the actual changes to the real grid. – Sven Nilsson Oct 29 '22 at 15:35
  • Side note: are you using tabs of size 1? That indentation won't do you any favors. – Nelfeal Oct 29 '22 at 15:55
  • @Nelfeal yes sorry, I just think its neater this way but its clear stack overflow disagrees. – Saw Oct 29 '22 at 16:31
  • @BOOTRE I've seen indentations of 2, 4, and even 8 spaces, but never just 1. If that works for you, fair enough. More importantly, you are mixing tabs and spaces. That's never a good idea. Typically people either use spaces only or tabs for indentation and spaces for alignment when needed. – Nelfeal Oct 29 '22 at 17:01

1 Answers1

0

So using @Nelfeal 's advice, I made a copy of the grid where I made the changes and once that was done I coloned the values back to the main grid. This fixed the problem.

#include <stdio.h>
#include <windows.h>
#include <GL/glut.h>

#define sleep(x) Sleep(1000 * (x))

#define sizeX 10
#define sizeY 10
#define wallSize 40

int frame = 0;

double grid[sizeY][sizeX];
double newGrid[sizeY][sizeX];
double filter[3][3] = {{1, 1, 1},
                       {1, 9, 1},
                       {1, 1, 1}};
                       

int width = 1000;
int height = 500;

double activation(double x){
    if(x == 3 || x == 11 || x == 12){
        return 1;
    }
    else{
        return 0;
    }
}

void CVFilter(){
    int x,y;
    double cv; //covolved value
    for(y=1;y<sizeY-1;y++){
  for(x=1;x<sizeX-1;x++){
    cv = (grid[y+1][x-1]*filter[0][0]) + (grid[y+1][x]*filter[0][1]) + (grid[y+1][x+1]*filter[2][2])+
         (grid[y][x-1]*filter[1][0]) + (grid[y][x]*filter[1][1]) + (grid[y][x+1]*filter[1][2])+
         (grid[y-1][x-1]*filter[2][0]) + (grid[y-1][x]*filter[2][1]) + (grid[y-1][x+1]*filter[2][2]);
            newGrid[y][x] = activation(cv);
  }
 }
}

void drawGrid(){
 int x,y;
 double rgb;
 glPointSize(wallSize);
 glBegin(GL_POINTS);
 for(y=0;y<sizeY;y++){
  for(x=0;x<sizeX;x++){
    rgb = grid[y][x];
    glColor3f(rgb,rgb,rgb);
    glVertex2i((x*wallSize),(y*wallSize));
  }
 }
 glEnd();
}

void cloneGrids(){
    int x,y;
    for(y=0;y<sizeY;y++){
  for(x=0;x<sizeX;x++){
    grid[y][x] = newGrid[y][x];
  }
 }
}

void display(){
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 if(frame == 1){
  CVFilter();
  cloneGrids();
 }
 if(frame == 2){
    sleep(1000);
 }
 //-----------------------Draw----------------------
 drawGrid();
 //-------------------------------------------------
 glutSwapBuffers();
 glutPostRedisplay();
 sleep(3);
 frame++;
}


void init(){
 glClearColor(0.3,0.3,0.3,0);
 gluOrtho2D(0,width,height,0);
}

void main(int argc, char** argv){ 
 grid[5][5] = 1; //Draws the glider
 grid[4][5] = 1; //Draws the glider
 grid[3][5] = 1; //Draws the glider
    grid[5][4] = 1; //Draws the glider
    grid[4][3] = 1; //Draws the glider
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
 glutInitWindowSize(width,height);
 glutCreateWindow("OpenGL");
 init();
 glutDisplayFunc(display);
 glutMainLoop();
}
Saw
  • 115
  • 1
  • 16