/****************************************************************************
 **
 ** Volumata.c        Jed Reynolds  Feb 1995
 **
 ** This is a nifty program that will output the contents of a box-bounded
 ** "game of life" into POV output style files for rendering. I pretty much
 ** just modified the code I already had for my "automata" program and 
 ** once again tought my self how to use fprintf. (DUH)
 **
 **************************************************************************/
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "volumata.h"
#include "CellOps.h"
/* #include "unixdef.h" */

/*****************************************************************************
 ** datatypes
 ****************************************************************************/

/* this is debug macro */
#define PM fprintf(stdout, " ** "); fflush(stdout);
#define FF fflush(stdout);
#define DB_

typedef MatrixType *Matrix;
/***************************************************************************
 ** main
 **************************************************************************/
void main(int argc, char *argv[]) 
{
  int interations = INTERATIONS;
  int r, i, j, k;
  void *t = NULL;
  char *filename;

  Matrix *Base, *Copy, *temp;

  /* startoff frill */
  if (argc == 3) {
    interations = atoi(argv[1]);
    filename = argv[2];
  } else {
    usage();
    return;
  }

  /* create the base matrix */
  Base = Create_Matrix(Base, BOTTOM, RIGHT, DEPTH);
 
  /* initialize copy matrix */
  Copy = Create_Matrix(Copy, BOTTOM, RIGHT, DEPTH);
 
  srand( (int)time(t) );

  /* remember Matrix[BOTTOM][RIGHT][DEPTH] */

  /* initialize living-room to random shit */
  for (k = FRONT +1; k < DEPTH - 1; k ++) {
    for (j=TOP+1; j < BOTTOM -1; j++) {
      for (i=LEFT +1; i < RIGHT-1; i++) {
	if ( (r = (random()*3)%3) ) {
	  Live(i, j, k, *Base);
	} else {
	  Die(i, j, k, *Base);
	}
      }
    }
  }
  
  /*
   * now it's time for the interation loop
   */
  printf("Interation: ");
  for (r=0; r<interations; r++) {
    
    /* display matrix */
    printf("%.3d, ", r);
    FF

    /* print out matrix */
    FPrint_Matrix(r, *Base, filename );
    
    /* interate matrix */
    Interate_Matrix(*Base, *Copy);
    
    /* swap matricies */
    temp = Base;
    Base = Copy;
    Copy = temp;
    
    printf("\b\b\b\b\b");
    FF
  } /* end of for */

  printf("%d. Done.\n", r-1); 
  FF
  return;
}/* end of main */

/***************************************************************************
 **  Display_Matrix
 **************************************************************************/
void Display_Matrix(Matrix m)
{
  int i, j,k, age;
#ifdef DB
  printf("I'm in Display_Matrix\n");
  FF
#endif
  printf("\n");
  for(j=TOP+1; j<BOTTOM-1; j++) {
    for(i=LEFT+1; i<RIGHT-1; i++) {
      /* printf("%d", Cell(i, j, m) ); */
      if ((age = Cell(i, j, k, m))) {
	if(age > MAXAGE/2) {
	  printf("B");
	} else if (age <= MAXAGE/4) {
	  printf(".");
	} else printf("o");
      }else{
	printf(" ");
      } /* end if */
    } /* end for */
    printf("\n");
  } /* end for */
  
  return;
}/* end of Display_Matrix */

/***************************************************************************
 ** FPrint_Matrix
 **
 ** This prints shit out in POV format, trippy, eh?
 **************************************************************************/
void FPrint_Matrix(int interation, Matrix m, char *passedname)
{
  int i, j, k;
  char filename[40]="EVIL\0";
  char temp[10]="\0";
  FILE *duhfile;

#ifdef DB
  printf("I'm in FPrint_Matrix\n");
  FF
#endif
    
    /*
     * create the filename
     */
    if (passedname != NULL ) {
      strcpy(filename, passedname);
    }
  sprintf(temp, "%.5d", interation);
  
  /* filename = */ strcat(filename, temp);
  
  /*
   * open the file, with a filename appended with 
   *  the number of the interation
   */
  
  if ( (duhfile=fopen( filename, "w" )) == NULL) {
    fprintf(stderr,"help me open this file!\n");
    exit (1);
  }
  
  /*
   * now print the file header, with any nessisary info
   */
  fprintf (duhfile, "// volumata data file, by Jed Reynolds\n");
  fprintf (duhfile, "#include \"colors.inc\"\n //#include \"shapes.inc\"\n");
  fprintf (duhfile, "#include \"textures.inc\"\n\n");
  fprintf (duhfile, "camera { location < %d, %d, %d >\n",
	   CAM_X, CAM_Y, CAM_Z);
  fprintf (duhfile, "         look_at < %d, %d, %d > }\n\n",
	   LOOK_X, LOOK_Y, LOOK_Z);
  fprintf (duhfile, "light_source { <500, -500, -500> color White } \n");
  fprintf (duhfile, "light_source { <500, 500, 500> color White } \n");
  fprintf (duhfile, "light_source { <-500, 500, 500> color White } \n");
  fprintf (duhfile, "light_source { <500, -500, 500> color White } \n");
  fprintf (duhfile, "light_source { <500, 500, -500> color White } \n\n");
  fprintf (duhfile, "sphere{ <0,0,0> 1000 ");
  fprintf (duhfile, "       texture { Blue_Sky ");
  fprintf (duhfile, "                scale < 300, 300, 300 > "); 
  fprintf (duhfile, "                translate < %d, %d, %d >     \n }\n  }\n",
	   interation, interation, interation);
  
  fprintf (duhfile,
	   "#declare CellColor = pigment { color red .25 green .5 blue .125 }\n");
  
  /*
   * now print out the spheres that are the cells
   */
  for(k=FRONT+1; k<DEPTH-1; k++) {
    for(j=TOP+1; j<BOTTOM-1; j++) {
      for(i=LEFT+1; i<RIGHT-1; i++) {

	/* 
	 * Print out the cell and it's size;
	 */
	fprintf(duhfile,"sphere{<%f, %f, %f>, %f",
		(float) GAP_X * i,
		(float) GAP_Y * j,
		(float) GAP_Z * k,
		(float) ((CELL_SCALE * Cell(i,j,k,m))  +.01)
		);
	fprintf(duhfile,"texture{ CellColor } translate < %d, %d, %d > }\n",
		TRANS_X, TRANS_Y, TRANS_Z );
	
      } /* end for i */
    } /* end for j*/
  } /* endfor k */
  
  /* now print the file trailer, if nessisary */
  fprintf(duhfile, "// end of volumata data file");
  
  /* now close the file */
  fclose(duhfile);
  
  return;
}/* end of FPrint_Matrix */

/***************************************************************************
 **  Interate_Matrix
 ***************************************************************************/
void Interate_Matrix(Matrix master, Matrix copy)
{
  int i, j, k, n;
#ifdef DB
  printf("I'm in Interate_Matrix\n");
  FF
#endif
    for (k = (FRONT+1); k < (DEPTH-1); k++) {
      
      for(j=(TOP+1); j<(BOTTOM-1); j++) {
	
	for (i=(LEFT+1); i<(RIGHT-1); i++) {
	  n = Neighbors(i, j, k, master);
	  
	  if ( (n < EXCESS) && (n > LONELY)) {
	    /* ideal living conditions */
	    if (n==LOVE) {
	      Live(i,j,k, copy);
	    } else {
	      Live_on(i,j,k, master, copy);
	    }
	  } else {
	    Die(i,j,k, copy);
	  } /* ENDIF for living and dying */

	} /* endfor i*/
      } /* endfor j */
    }/* endfor k */
} /* end of Interate_Matrix */



/***************************************************************************
 **  Usage
 **************************************************************************/
void usage()
{
  char message[]="Jed's Cellular AutoMart Imporium:\n 'volo [interations] [outfilename]', please.";
  fprintf(stderr, "%s\n", message);
  return;
}
/* eof */
