//strangeLife2.h
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define N_MAX 65	  // lato della matrice
#define ELEM_RANGE2 2 // concentrazione in matrice di cellule


// prototipi delle funzioni di libreria

void riempi_Matrice(int a[][N_MAX]);

void stampa_Matrice(int a[][N_MAX]);

void aggiorna_Matrice(int a[][N_MAX]);

void riempiMatrice1(int a[][N_MAX]);

void triangoloAlCentro (int a[][N_MAX]);

void aggiungiAliante(int a[][N_MAX]);

void aggiungiStormo(int a[][N_MAX]);

// segue il codice delle funzioni da portare in libreria

void riempiMatrice(int a[][N_MAX])
{
   int i, j, num_random;
   float temp;
   int n = N_MAX; // per comodita' chiamo n N_MAX

   // Genero una sequenza casuale per riempire la matrice
   srand(time(NULL));
   for(i=0;i < n;i=i+1)
   {
      for (j=0;j < n;j=j+1)
      {
         num_random = rand();  // qui genero un numero casuale
         temp =  (num_random * ELEM_RANGE2) / RAND_MAX  ; 
         			
         a[i][j]= (int)floor( temp );  
         // il float ritorna ad essere un intero
         if ( a[i][j] ) 
            a[i][j]=1;
      }
   }
}

void stampa_Matrice(int a[][N_MAX]) // notare che qui non si usa il ;
{
   int i;
   int j;
   int n = N_MAX; // per comodita' chiamo n N_MAX

   //stampo una matrice facendo anche i "bordini"	
   // -------- Quindi una riga  (1)
   // |      |	Un carattere "|" all'inizio ed un "|" alla fine (2)e(3)
   // |      |	idem 
   // --------	Una riga per chiudere (4)

   for(i=0;i < n+2;i=i+1) printf("_");  // (1) una riga lunga quanto una matrice
		
   for(i=0;i < n;i=i+1)
   {
      printf("\n");  // andiamo a capo
      printf("|");   // "|" all'inizio e (2)

      for (j=0;j < n;j=j+1)
      {
         if (a[i][j]==1) 
         {	
            printf("@");
         }
         else
         {
            printf(" ");
         }
      }
		
      printf("|"); // "|" alla fine e (3)
   }
   printf("\n");   // andiamo a capo e tiriamo la riga
   for(i=0;i < n+2;i=i+1) printf("_");  // (4) una riga lunga quanto una matrice
   printf("\n\n");
}
void aggiorna_Matrice (int a[][N_MAX])
// il codice e'stato volutamente semplificato
{
   int i, j, ki, kj ,tot;

   int n = N_MAX; // per comodita' chiamo n N_MAX
   int stato[N_MAX][N_MAX];
	
   // considero anche le cellule nei bordi supponendo che le celle al di fuori 
   // della matrice siano semplicemente vuote.
	
   for(i=0;i < n;i=i+1)
   {
      for (j=0;j < n;j=j+1)
      {
         // ispeziono le 9 celle della matrice 3x3
         // e sottraggo la cella centrale
         tot = 0;
         for (ki=i-1; ki <= i+1;ki=ki+1)
         {
            for (kj=j-1; kj <= j+1;kj=kj+1)
            {
               //escludo le celle che non sono nella matrice
               if ((0 <= ki &&  ki < n) && (0 <= kj && kj < n))
                  tot = tot + a[ki][kj];
            }
         }
         tot = tot - a[i][j] ;  // guardo solo l'intorno
         
         // applico le regole di Conway, (ma sono giuste?)
         if ((a[i][j] == 0) &&  (tot == 3)) 
         {
            stato[i][j] =1;
         } 
         else if ((a[i][j] == 1) &&  ( (tot == 3) || (tot == 2)) )  
         {
            stato[i][j] =1;
         } 
         else 
         {
            stato[i][j] =0;
         }
      }
   }
	
   // copio lo stato sulla matrice a
   for(i=0;i < n;i=i+1)
   {
      for (j=0;j < n;j=j+1)
      {
         a[i][j] = stato[i][j];
      }
   }
}

// INIZIO CODICE ESERCIZIO


void riempiMatrice1(int a[][N_MAX]) //inizializza tutte le celle a 1
{
   int i, j;
   int n = N_MAX; // per comodita' chiamo n N_MAX
	
   for(i=0;i < n;i=i+1)
   {
      for (j=0;j < n;j=j+1)
      {
         a[i][j]=1;
      }
   }
}


// inizializza a 1 solo le celle al centro
// in un intorno triangolare
//             
//             
//      1       
//     111       
//    11111        
//   1111111        
// 


//PENSACI BENE PRIMA DI GUARDARE LA SOLUZIONE!
void triangoloAlCentro (int a[][N_MAX]) 
{
   int i,j;
   int n = N_MAX; // per comodita' chiamo n N_MAX
   int k = 2; // misura il triangolo k = altezza/2
   
   // le prime righe sono vuote 
   for (i=0; i<(n/2 - k); i++)
     for (j=0; j< n;j++)
         a[i][j]=0;
   
   for (i=(n/2 - k); i<(n/2 + k); i++)
   {
      // prima inserisco gli zeri a sinistra 
      for (j=0; j< (n-k-i);j++)
         a[i][j]=0;
         
      // poi inserisco gli  "1" 
      for (j=(n-k-i) ; j < (n - 2*(n/2)+ k +i +1) ;j++)
         a[i][j]=1;
      
      // poi inserisco gli zeri a destra    
      for (j= (n - 2*(n/2)+ k +i +1) ; j< n;j++)
         a[i][j]=0;
   }  
   // le ultime righe sono vuote       
   for (i=(n/2 + k); i<n; i++)

     for (j=0; j< n;j++)
         a[i][j]=0;
}

// data la matrice questa procedura
// AGGIUNGE un aliante in posizione casuale (vedi lezione) 
// (Somma gli elementi facendo gli OR elemento ad elemento fra le matrici)
// Viene chiamato glider (letteralmente "aliante") il pił piccolo organismo 
// semovente che possa essere rappresentato all'interno del Gioco della Vita.
// Ecco un esempio
//  @
//   @
// @@@
//
void aggiungiAliante(int a[][N_MAX])
{
   int i, j;
   int n = N_MAX; // per comodita' chiamo n N_MAX
   int temp[N_MAX][N_MAX];
   
	 
   //inizializzo la matrice che conterra' un aliante
	for(i=0;i < n;i=i+1)
   {

      for (j=0;j < n;j=j+1)
      {
         temp[i][j]=0;
      }
   }
		
   // Genero una sequenza casuale per scieglere le cordinate del primo 
   // elemento dell'aliante (quello in alto)
   
   srand(time(NULL));
      
   i= rand()%(n-3); // qui genero un numero casuale per i tra 0 e N_MAX-3
   j= rand()%(n-2)+1; // qui genero un numero casuale per j tra 1 e N_MAX-2
    
    // costruisco l'aliante con la punta alta in temp[i][j]
   temp[i][j]= 1;
   temp[i+1][j+1]= 1;
   temp[i+2][j-1]= 1;
   temp[i+2][j]= 1;
   temp[i+2][j+1]= 1;
   
   // inserisco l'aliante in a 
   
   for(i=0;i < n;i=i+1)
   {
      for (j=0;j < n;j=j+1)
      {
         a[i][j]= (a[i][j] || temp[i][j]);
      }
   }
}

// iterando aggiungiAliante si inserisce uno stormo di 30 alianti
// disposti casualmente
void aggiungiStormo(int a[][N_MAX])
{
   int i,j;
   int n_alianti =30;
   for(i=0;i < n_alianti;i=i+1)
   {
    aggiungiAliante(a);
    for(j=0;j < 99999999;j=j+1);
    //perdo tempo per far generare dei numeri random diversi
   }
}