/****************************************************************************
 ** create a matrix
 **
 ** This returns a pointer to a fully initialized matrix. There should be
 ** no need to initialize if from any upper level.
 ****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include "CellOps.h"

/* datatype for matrix */
/* typedef Matrix_Type *Matrix; */

Matrix Create_Matrix(Matrix target, int x, int y, int z)
{
  int i, j, k;

  target = (Matrix)malloc(sizeof(**Matrix[x][y][z]));
  if ( target == NULL )
    {
      fprintf(stderr,"Volumata:CellOps.c:Create_Matrix: Can't make matrix.\n");
      exit(1);
    }
  for (k = 0; k<z; k++)
    {
      for(j = 0; j<y; j++)
	{
	  for (i=0; i<x; i++)
	    {
	      Die(i,j,k, target);
	    }
	}
    }
  return target;
} /* end of Create_Cell */

/**************************************************************************
 **  Neighbors
 **
 **  Returns the number of cells adjacent with ages > 0. These are the
 **  neighboring cells.
 *************************************************************************/
int Neighbors(int i, int j, int k, Matrix m)
{
  int n;

#ifdef DB
  printf("I'm in Neighbors\n");
  FF
#endif
    /* count the number of neighbors a cell has */
    /* I might want to do some error checking on bounds...*/
    n=0;

#if 0  
  /*
   * I'm going to keep this code in here because
   * it's actually useful, if I ever need to compute the
   * age of a cell-group or cell-block.
   *
   * This code WAS only good if Cell returns 1. With aging,
   * it returns the age of the cells around the called point.
   */
  n = Cell(i-1,j-1,k-1, m) + Cell(i,j-1,k-1, m) + Cell(i+1,j-1,k-1, m) +
    Cell(i-1,j,k-1, m) +Cell(i,j,k-1, m) +  Cell(i+1,j,k-1, m) +
      Cell(i-1, j+1,k-1, m) + Cell(i,j+1,k-1 m) + Cell(i+1,j+1,k-1 m);
  
  n = n + Cell(i-1,j-1,k, m) + Cell(i,j-1,k, m) + Cell(i+1,j-1,k, m) +
    Cell(i-1,j,k, m) + Cell(i+1,j,k, m) +
      Cell(i-1, j+1,k, m) + Cell(i,j+1,k, m) + Cell(i+1,j+1,k, m);
  
  n = n + Cell(i-1,j-1,k+1, m) + Cell(i,j-1,k+1, m) + Cell(i+1,j-1,k+1, m) +
    Cell(i-1,j,k+1, m) + Cell(i, j, k+1, m) + Cell(i+1,j,k+1, m) +
      Cell(i-1, j+1,k+1, m) + Cell(i,j+1,k+1 m) + Cell(i+1,j+1,k+1 m);
  
#else
  /* with the advent of aging, the value of just Cell changes ranges
     as a boolean */
  /* since all we have to do here is calc the number of cells, a 0 age
     means no cell...non-0 means cell */
  
  /* forward slice*/
  if(Cell(i-1, j-1, k-1, m)) n++;
  if(Cell(i, j-1, k-1, m)) n++;
  if(Cell(i+1, j-1, k-1, m)) n++;
  
  if(Cell(i-1, j, k-1, m)) n++;
  if(Cell(i, j, k-1, m)) n++;
  if(Cell(i+1, j, k-1, m)) n++;
  
  if(Cell(i-1, j+1, k-1, m)) n++;
  if(Cell(i, j+1, k-1, m)) n++;
  if(Cell(i+1, j+1, k-1, m)) n++;
  
  /*middle slice*/
  if(Cell(i-1, j-1, k, m)) n++;
  if(Cell(i, j-1, k, m)) n++;
  if(Cell(i+1, j-1, k, m)) n++;
  
  if(Cell(i-1, j, k, m)) n++;
  if(Cell(i+1, j, k, m)) n++;
  
  if(Cell(i-1, j+1, k, m)) n++;
  if(Cell(i, j+1, k, m)) n++;
  if(Cell(i+1, j+1, k, m)) n++;
  
  /*back slice*/
  if(Cell(i-1, j-1, k+1, m)) n++;
  if(Cell(i, j-1, k+1, m)) n++;
  if(Cell(i+1, j-1, k+1, m)) n++;
  
  if(Cell(i-1, j, k+1, m)) n++;
  if(Cell(i, j, k+1, m)) n++;
  if(Cell(i+1, j, k+1, m)) n++;
  
  if(Cell(i-1, j+1, k+1, m)) n++;
  if(Cell(i, j+1, k+1, m)) n++;
  if(Cell(i+1, j+1, k+1, m)) n++;
  
#endif
  
  return n;
}


/*************************************************************************
 ** Live_on
 **
 ** Evaluates whether a cell should live on or not.
 ** Cute modification to kill more cells added, reduces static
 ** patterns. Implimented aging, too.
 *************************************************************************/
void Live_on(int i, int j, int k, Matrix master, Matrix copy)
{
#ifdef MORE_DETH
  int r = (random()*3)%2;
#endif
  
  int age;
  
#ifdef DB
  printf("I'm in Live_on\n");
  FF
#endif
    
#if MORE_DETH
    if(!r) {
      Die(i,j,k, copy);
      return;
    }
#endif
  
#ifdef AGING
  age = 1+Cell(i,j,k,master);
  if (age > MAXAGE) {
    Die(i,j,k,copy);
  } else {
    *copy[i][j][k] = age;
  }  /* printf("age=%d ", age);*/
#else
  *(*copy[i][j][k]) = *(*master[i][j][k]);
#endif
}

/*************************************************************************
 **  Live
 **
 **  Set the age of a cell to 1. It now lives.
 *************************************************************************/
void Live(int i, int j, int k, Matrix m)
{
#ifdef DB
  printf("I'm in Live");
  FF
#endif
    
   **m[i][j][k] = 1;
  return;
}

/**************************************************************************
 **  Die
 **
 **  Set a matrix cell to zero. This Means Death!
 **************************************************************************/
void Die(int i, int j, int k, Matrix m)
{
#ifdef DB
  printf("I'm in Die");
  FF
#endif
    m[i][j][k] = 0;
}


/**************************************************************************
 ** Cell
 **
 ** This returns the matrix points i,j,k. This is the age of the cell.
 **************************************************************************/
int Cell(int i, int j, int k, Matrix m)
{
#ifdef DB
  printf("I'm in Cell");
  FF
#endif
/*   printf(" i=%d,j=%d ", i, j); */
  return m[i][j][k];
}

/* eof */
