/* cells.c by Jack Carrozzo
 * Copyright 2005
 * http://www.crepinc.com/
 * jack {[@]} crepinc.com
 */

#include <stdio.h>
#include <stdlib.h>

#define N 200 //size of Cell Grid
#define RANDDIVTHIRD 10666
//601429794 for linux, 10666 for win
#define RANDDIVHALF 16000
//902144691 for linux, 16000 for win

/*   Cell States:
 *  0   : doesn't exist
 *  1   : just born
 *  2-3 : chillin'
 *  4-5 : can reproduce
 *  6   : living, can't split
 *  7   : dead
 */
 
/*  About Neighbors:
 * 0  : -4
 * 1  : -3
 * 2  : -1
 * 3  : 0
 * 4-5: +2
 * 6  : +1
 * 7  : -1
 * 8  : -3
 */

int Cells[N][N]; //grid of cells
int i,j; //the amazing ubiquitous I (and j)
int Splits=0;

void ShowCells( void ) {

     int show=0;
     for (i=0;i<N;i++) {
         printf("\n");
         for (j=0;j<N;j++) {
             /*show=0;
             if (Cells[i][j]!=0) { //mShowCells();ake sure it exists
                if (Cells[i][j]!=7) { //make sure its not dead
                   show=1;
                }
             }
             if (show==1)
                 printf("0");
             else
                 printf("-");*/
                 printf("%d",Cells[i][j]);
         }
     }

     printf("\n\n");
}

void InitGrid( void ) {
     int r;
     for (i=0;i<N;i++)
         for (j=0;j<N;j++)
             Cells[i][j]=0;

     //srand (time (0)); //did it in main
     for (i=0;i<N;i++) {
         for (j=0;j<N;j++) {
             r = rand();
             //printf("rand %d\n",r);
             if (r<=RANDDIVHALF) {
                Cells[i][j]=1;
                //printf("Set Cell %d %d\n",i,j);
             }
         }
     }
}            

void ProcessCells( void ) {

     int NumNeighbors=0;
     int ReprodSpace=0;
     int Reprod=0;
     
     for (i=0;i<N;i++)
         for (j=0;j<N;j++) 
             if (Cells[i][j]==7) {
                if (rand()>=RANDDIVTHIRD) {
                   Cells[i][j]=0; //make dead cells not exist
                } else {
                   Cells[i][j]=2; //randomly comes alive again ;-)
                }
             } else {//grow from the ground
                if (rand()>=RANDDIVTHIRD) {
                    Cells[i][j]=2;
                }
             }

     for (i=0;i<N;i++) {
     //for (i=1;i<(N-1);i++) {
         for (j=0;j<N;j++) {
         //for (j=1;j<(N-1);j++) {
	     NumNeighbors=0;

	     if (Cells[i][j]!=0) {
                 if (Cells[i-1][j]==0) NumNeighbors++;
                 if (Cells[i-1][j+1]==0) NumNeighbors++;
                 if (Cells[i][j+1]==0) NumNeighbors++;
                 if (Cells[i+1][j+1]==0) NumNeighbors++;
                 if (Cells[i+1][j]==0) NumNeighbors++;
                 if (Cells[i+1][j-1]==0) NumNeighbors++;
                 if (Cells[i][j-1]==0) NumNeighbors++;
                 if (Cells[i-1][j-1]==0) NumNeighbors++;
                 //printf("doing cell %d %d. It has %d neighbors.\n\n",i,j,NumNeighbors);

                 /* if (NumNeighbors==0) Cells[i][j] += (-4);
                 if (NumNeighbors==1) Cells[i][j] += (-3);
                 if (NumNeighbors==2) Cells[i][j] += (-1);
                 if (NumNeighbors==3) Cells[i][j] += (0);
                 if (NumNeighbors==4) Cells[i][j] += (2);
                 if (NumNeighbors==5) Cells[i][j] += (2);
                 if (NumNeighbors==6) Cells[i][j] += (1);
                 if (NumNeighbors==7) Cells[i][j] += (-1);
                 if (NumNeighbors==8) Cells[i][j] += (-3); */

		 if (NumNeighbors==0) Cells[i][j] += (-4);
                 if (NumNeighbors==1) Cells[i][j] += (2);
                 if (NumNeighbors==2) Cells[i][j] += (1);
                 if (NumNeighbors==3) Cells[i][j] += (0);
                 if (NumNeighbors==4) if (Cells[i][j]>5) {
                                      Cells[i][j] += (-1); }
                 if (NumNeighbors==5) if (Cells[i][j]>5) {
                                      Cells[i][j] += (-1); }
                 if (NumNeighbors==6) Cells[i][j] += (0);
                 if (NumNeighbors==7) Cells[i][j] += (1);
                 if (NumNeighbors==8) Cells[i][j] += (2);

		 if (Cells[i][j]<=0) Cells[i][j]=0;

                 if (NumNeighbors==4 || NumNeighbors==5) {//think about babies
                    if (Cells[i][j]==2 || Cells[i][j]==3 || Cells[i][j]==4 || Cells[i][j]==5 || Cells[i][j]==6) {
                       if (rand()<=RANDDIVHALF) {
		               //if (2<5) { //always
                          if (Cells[i-1][j]==0) ReprodSpace=1;
                          if (Cells[i-1][j+1]==0) ReprodSpace=2;
                          if (Cells[i][j+1]==0) ReprodSpace=3;
                          if (Cells[i+1][j+1]==0) ReprodSpace=4;
                          if (Cells[i+1][j]==0) ReprodSpace=5;
                          if (Cells[i+1][j-1]==0) ReprodSpace=6;
                          if (Cells[i][j-1]==0) ReprodSpace=7;
                          if (Cells[i-1][j-1]==0) ReprodSpace=8;
			  //printf("reproducing from cell %d,%d\n",i,j);

			  Reprod =0;
                          if (ReprodSpace==1) { if (Reprod==0) Cells[i-1][j]=1; Reprod=1; }
                          if (ReprodSpace==1) { if (Reprod==0) Cells[i-1][j+1]=1; Reprod=1; }
                          if (ReprodSpace==1) { if (Reprod==0) Cells[i][j+1]=1; Reprod=1; }
                          if (ReprodSpace==1) { if (Reprod==0) Cells[i+1][j+1]=1; Reprod=1; }
                          if (ReprodSpace==1) { if (Reprod==0) Cells[i+1][j]=1; Reprod=1; }
                          if (ReprodSpace==1) { if (Reprod==0) Cells[i+1][j-1]=1; Reprod=1; }
                          if (ReprodSpace==1) { if (Reprod==0) Cells[i][j-1]=1; Reprod=1; }
                          if (ReprodSpace==1) { if (Reprod==0) Cells[i-1][j-1]=1; Reprod=1; }
			  Splits++;
                       }
                    }
                 }
             }
	 }
     }
}

int CountLive( void ) {
    int num=0;

    for (i=0;i<N;i++)
        for(j=0;j<N;j++) {
	    if (Cells[i][j]!=0)
	    	if (Cells[i][j]!=7)
		    num++;
	}

    return num;
}

int main(int argc, char *argv[]) {
    int q=0;

    InitGrid();
    srand (time (0));

    //ShowCells();

    for (q=0;q<1500;q++) {
        ProcessCells();
        printf("%d, %d\n",q,CountLive());
	    //ShowCells();
    } 
    //printf("%d, %d\n",q,CountLive());
    //ShowCells();

    //printf("There were %d splits.\n",Splits);

    //system("pause");
    return 0;
}
