int sx, sy; 
float density = 0.3; 
int[][][] world;

boolean gameplaying = false;


float ballXPos,ballYPos;

int ballX,ballY;
int livejuice;
boolean virgin = true;
int score;

int goalx, goaly;


void mousePressed(){
   if(!gameplaying ){
     gameplaying = true;
     restart();
   }
   virgin = false;
}

void restart(){
      score = 0;
     livejuice = 100; 
  world = new int[sx][sy][2]; 

  ghostx = random(300);
  ghosty = random(300);


  // Set random cells to 'on' 
  for (int i = 0; i < sx * sy * density; i++) { 
    world[(int)random(sx)][(int)random(sy)][1] = 1; 
  } 

  ballX=25;
  ballY=25;
  //clear shit around
  for(int x = 20; x < 30;x++){
    for(int y = 20; y < 30;y++){
      world[x][y][0]=0; 
      world[x][y][1]=0;
    }
  }

  livejuice=100;
  goalx = int(random(50));
  goaly = int(random(50));

  
  
}

float ghostx,ghosty,ghostxspeed,ghostyspeed;
float gs = 40;
void setup() 
{ 

  size(400, 400);
   textAlign(CENTER);
  textFont(loadFont("Arial-Black-14.vlw"),14);

  framerate(30);
  sx = width / 8;
  sy = height / 8;

restart();
} 

void draw() 
{ 
  background(128); 

  updateCells(); 

  world[goalx][goaly][0] = 0;
  world[goalx][goaly][1] = 0;
  fill(255);
  text("life:"+livejuice,300,20);
  text("score:"+score,100,20);

  if(goalx == ballX && goaly == ballY){
    score++;
    goalx = int(random(50));
    goaly = int(random(50));
    drawgoal();
  }

  moveghost();


  drawgoal();
  
  if(gameplaying){
  drawBall();
  }
    drawghost();


  if(random(2)<1){
    int basex = int((ghostx+(gs/2)) / 8) ; 
    int basey =int((ghosty+(gs/2)) / 8) ;
   
    for(int i = 0; i < int(random(8));i++){
      int newx = basex + int(random(5))-2;
      int newy = basey + int(random(5))-2;
    if(newx >= 0 && newx < 50 && newy >= 0 && newy < 50){
                world[newx][newy][0] = 1;
    }
    }
  }
  

if(gameplaying){
  if(world[ballX][ballY][0] == 1){
    livejuice-=2; 
     if(livejuice <= 0){
        gameplaying = false;
     }   
  }
} else { //game not playing, show screen
  if(virgin){
      showtitle();
  } else {
     showgameover();
    
  }
  
}


} 

// Count the number of adjacent cells 'on' 
int neighbors(int x, int y) 
{ 
  return world[(x + 1) % sx][y][0] + 
    world[x][(y + 1) % sy][0] + 
    world[(x + sx - 1) % sx][y][0] + 
    world[x][(y + sy - 1) % sy][0] + 
    world[(x + 1) % sx][(y + 1) % sy][0] + 
    world[(x + sx - 1) % sx][(y + 1) % sy][0] + 
    world[(x + sx - 1) % sx][(y + sy - 1) % sy][0] + 
    world[(x + 1) % sx][(y + sy - 1) % sy][0]; 
} 
void updateCells(){
  stroke(0);
  fill(128,0,0);
  // Drawing and update cycle 
  for (int x = 0; x < sx; x=x+1) { 
    for (int y = 0; y < sy; y=y+1) { 
      //if cell TOBE born, or cell NOWIS alive and TOBO no change...
      if ((world[x][y][1] == 1)|| (world[x][y][0] == 1 && world[x][y][1] == 0) ) 
      { 
        //NOWIS ALIVE
        world[x][y][0] = 1; 

        rect(x*8,y*8,6,6);
      } 
      //if cell TOBE killed  
      if (world[x][y][1] == -1) 
      { 
        //NOWIS dead
        world[x][y][0] = 0; 
      } 
      //TOBE nochange...
      world[x][y][1] = 0; 
    } 
  } 
  // Birth and death cycle 
  for (int x = 0; x < sx; x=x+1) { 
    for (int y = 0; y < sy; y=y+1) { 
      int count = neighbors(x, y); 
      //if 3 neighbors and NOWIS dead...
      if (count == 3 && world[x][y][0] == 0) 
      { 
        //TOBE born
        world[x][y][1] = 1; 
      } 
      //if too few, too many neighbors and NOWIS alive
      if ((count < 2 || count > 3) && world[x][y][0] == 1) 
      { 
        //TOBE killed
        world[x][y][1] = -1; 
      } 
    } 
  } 
}

void drawgoal(){
  stroke(random(255),random(255),random(255));
  float goalxpos = goalx *8;
  float goalypos = goaly *8;
  line(goalxpos+4, goalypos+0,goalxpos+4, goalypos+8);
  line(goalxpos+0, goalypos+4,goalxpos+8, goalypos+4);
}


void drawBall(){

  ballXPos = ballX *8;
  ballYPos = ballY *8;

  int xsquare = int(ballXPos / 8);
  int ysquare = int(ballYPos / 8);

  if(world[xsquare][ysquare][0] == 1){
    fill(0,255,0);
  }
  else{
    fill(255,255,0);
  }    

  stroke(0);
  rect(ballXPos,ballYPos,8,8); 
  line(ballXPos+2,ballYPos+5,ballXPos+4,ballYPos+6);
  line(ballXPos+5,ballYPos+6,ballXPos+6,ballYPos+5);
  line(ballXPos+2,ballYPos+2,ballXPos+2,ballYPos+3);
  line(ballXPos+6,ballYPos+2,ballXPos+6,ballYPos+3);

}




void keyPressed(){

  if(keyCode == 37){
    if(ballX > 0)ballX --;
  }
  if(keyCode == 39){
    if(ballX < 49) ballX++;
  }
  if(keyCode == 38){
    if(ballY > 0)ballY --;
  }
  if(keyCode == 40){
    if(ballY < 49) ballY++;
  }

}



void drawghost(){
  noStroke();



  fill(255,255,255,30);
  rect(ghostx,ghosty,gs,gs);
  fill(0,0,0,30);
  rect(ghostx+(gs/5),ghosty+(gs/5),gs/5,gs/5);
  rect(ghostx+(gs*3/5),ghosty+(gs/5),gs/5,gs/5);
  rect(ghostx+(gs/5),ghosty+(gs*3/5),gs*3/5,gs/5);

}


void moveghost(){
  ghostxspeed += random(1)-.5; 
  ghostyspeed += random(1)-.5;

  ghostx += ghostxspeed;
  ghosty += ghostyspeed;

  if(ghostx < 0){
    ghostxspeed = 1; 
  }
  if(ghostx > 400-gs){
    ghostxspeed = -1; 
  }
  if(ghosty < 0){
    ghostyspeed = 1; 
  }
  if(ghosty > 400-gs){
    ghostyspeed = -1; 
  }

}

void showtitle(){
  fill(255);
    text("CONWAY WEST",200,80);
        text("welcome to john conway's game of life!",200,120);
        text("but the evil ghost of random may make it...",200,160);
        text("YOUR DEATH!!!!!! muahahahahahahahaha",200,180);

        text("you are the happy face",200,260);
        text("collect the colorful cross for points",200,280);
        text("avoid the red frothing squares",200,300);
        text("the ghost won't hurt you",200,320);
        text("but the squares he leaves behind might!",200,340);
        text("CLICK TO START, ARROW KEYS TO MOVE",200,370);
        
}


void showgameover(){
  fill(255);
    text("CONWAY WEST",200,80);
        text("game over",200,120);
        text("your score:"+score,200,160);
        text("CLICK TO RESTART, ARROW KEYS TO MOVE",200,370);
        
}