#include "DEM.h"

#define LOAD_BACKUP 1

//struct Thread_I *thread_i;
//struct Thread_I *thread_di_i;
//pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
//pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
//int Image_Locked;

static void Adjust_Sea_Level(int load){
	//unsigned int height = ia->height;
	//unsigned int width  = ia->width;
	//unsigned int count1, count2;
	//unsigned char rgb[3];
	static int sea_level_chng = 100;
	static int is_rising = 0;

	if(load){
		sea_level_chng = ia->cur_sealevel;
		is_rising = ia->sea_rising;
		return;
	}
	//if(change){
		if(is_rising){
			if(sea_level_chng == 100){
				is_rising = 0;
			}else{
				sea_level_chng++;
			}
		}else{
			if(sea_level_chng == -128){
				is_rising = 1;
			}else{
				sea_level_chng--;
			}
		}
	//}
	ia->cur_sealevel = sea_level_chng;
	ia->sea_rising = is_rising;

		/*
		for(count1=0; count1<height; count1++){
			for(count2=0; count2<width; count2++){
				if(ia->data[count1][count2]<sea_level_chng){
					rgb[0] = 0;
					rgb[1] = 0;
					rgb[2] = 255;
				}else{
					rgb[0] = 0;
					rgb[1] = 255;
					rgb[2] = 0;
				}
				ia->image[count1*width*3+(count2*3)] = rgb[0];
				ia->image[count1*width*3+(count2*3+1)] = rgb[1];
				ia->image[count1*width*3+(count2*3+2)] = rgb[2];
			}
		}
		//sleep(1);
	//}
	*/
	//return sea_level_chng;
}

static void Adjust_Climate(int load){
    static float temp_chng = 32; //starting at high temp
    static int is_rising = 0;
	//every 10K years you'll get a 2c temp change

    if(load){
        temp_chng = ia->cur_temp;
        is_rising = ia->temp_rising;
        return;
    }
	if(is_rising){
        if(temp_chng > 32){
             is_rising = 0;
         }else{
            temp_chng+=0.2;
         }
	}else{
       if(temp_chng < 28){
           is_rising = 1;
       }else{
           temp_chng-=0.2;
       }
	}
    ia->cur_temp = temp_chng;
    ia->temp_rising = is_rising;
}

int Load_Terrain(char *filename){
	FILE *fp = fopen(filename, "rb");
	if(!fp){
		printf("Error opening file: %s\n", filename);
		return 1;
	}
	//printf("here 1\n");
	//NROWS         6000
	//NCOLS         4800
	//unsigned int height = 41600;
	//unsigned int width = 43200;
	const int start_sealevel = 100;
	unsigned int height = 1800; //40
	unsigned int width  = 3600; //27

	ia = malloc(sizeof(struct image_attr));
	ia->image = malloc(sizeof(unsigned char)*height*width*3);
    ia->width = width;
    ia->height = height;
	ia->cur_sealevel = start_sealevel;
	ia->sea_rising = 0;
	ia->cur_temp = 32;
	ia->temp_rising = 0;
	//printf("here 2\n");
	//ia->data = (int16_t **)malloc(sizeof(int16_t *)*height);

	//double temp[27][40];
	//unsigned int temp_x = 0;
	//unsigned int temp_y = 0;

	char two_b[2];
	//u_int16_t
	union{ char a[2]; int16_t b;}x;
	unsigned int count1, count2;
	//int result = 0;
	unsigned char rgb[3];
	//unsigned int data_pnt_x = 0;
	//unsigned int data_pnt_y = 0;
	//unsigned int data_sum = 0;

	ia->data = (int16_t **)malloc(sizeof(int16_t *)*height);
	for(count1=0; count1<height; count1++){
		ia->data[count1] = (int16_t *)malloc(sizeof(int16_t)*width);
	}
	for(count1=0; count1<height; count1++){
		//if(temp_y == 39)
		//	temp_y = 0;
		//for(temp_y=0; temp_y<40; temp_y++;
		/*
		temp_y++;
		if(temp_y!=40){
			for(count2=0; count2<src_width; count2++){
				fread(&two_b, 1, 2, fp);
			}
		}
		if(temp_y==40){
			temp_y = 0;
		*/
			for(count2=0; count2<width; count2++){

				fread(&two_b, 1, 2, fp);
				x.a[0] = two_b[0];
				x.a[1] = two_b[1];
				ia->data[count1][count2] = x.b;
				//temp_x++;
				//if(temp_x==27){
				//	temp_x=0;

					//data_sum += x.b;
					//data_pnt++;
					//if(x.b > 0){
					//	result = 
					//if(count1 < 20 && count2 < 20)
					//	printf("%d\n", x.b);
					//if(x.b != 12)
					//	printf("hmm\b");
					//1 -9999 5825 -2347.6 4873.5
					//the band number, minimum value, maximum value, mean value, and standard deviation of the values in the raster

					//if(data_pnt == src_width){
					//	x.b = ceil(data_sum/src_width);
					//	data_pnt = 0;
//						if(x.b < -9999)
//							printf("low !\n");
//						if(x.b > 5825)
//							printf("high !\n");

/*						if(x.b<-5000){
							rgb[0] = 0;
							rgb[1] = 0;
							rgb[2] = 0; //ceil(255-(x.b/-13000)*255);
						}else if(x.b<-2500){
							rgb[0] = 0;
							rgb[1] = 0; //ceil(255-(x.b/-2500)*255);
							rgb[2] = 255;
						}else if(x.b<-1000){
							rgb[0] = 0;
							rgb[1] = 0;
							rgb[2] = 128; //ceil(255-(x.b/-1000)*255);
						}else if(x.b<-500){
							rgb[0] = 0; //ceil((x.b/-500)*255);
							rgb[1] = 128;
							rgb[2] = 128;

						}else*/ if(x.b < start_sealevel){
							rgb[0] = 0;
							rgb[1] = 0; //ceil(255-(x.b/-50)*255);
							rgb[2] = 255;
						}else{
							rgb[0] = 0;
							rgb[1] = 255;
							rgb[2] = 0;
						}
/*						
						black -13000
						blue -4000
						turquise 0
						green 3000
						yellow 6000
						red 9000
						-13000
						-6000
						0
						4000
						9000
						*/
						ia->image[count1*width*3+(count2*3)] = rgb[0];
						ia->image[count1*width*3+(count2*3+1)] = rgb[1];
						ia->image[count1*width*3+(count2*3+2)] = rgb[2];
					
			
			
		}
	}

	

	fclose(fp);
	return 0;
}



static void Gen_Detailed_Counts(unsigned int year, unsigned int regions){
	//printf 10 most numerous species info
	unsigned int h, w;
	unsigned int height = ia->height;
	unsigned int width = ia->width;
	unsigned int total_living = 0;
	//static unsigned int last_year = 1;
	uint32_t chng = 0;

	//struct Details{
	//	unsigned int total_numbers;
	//	struct Species type;
	//}details[10];

	//damnit !
	for(h=0; h<height; h++){
		for(w=0; w<width; w++){
			if(life[h][w]->alive){
				total_living++;

			}
		}
	}
	printf("Year: %u\n", year); 
	//Total Living: %u\n", year, total_living);
	for(h=0; h<regions; h++){
            stats_t.disease += stats[h].disease;
            stats_t.drown += stats[h].drown;
			stats_t.exposure += stats[h].exposure;
            stats_t.old_age += stats[h].old_age;
            stats_t.died_attacking += stats[h].died_attacking;
            stats_t.died_defending += stats[h].died_defending;
            stats_t.new_life += stats[h].new_life;
            stats_t.new_species += stats[h].new_species;
	}
	printf("\tdisease: %lu\n", stats_t.disease);
	for(h=0; h<regions; h++){
		chng += stats[h].disease;
	}
	printf("\t\tchng: %u\n",chng); 

	printf("\tdrown: %lu\n", stats_t.drown);
	chng=stats[0].drown;
	for(h=1; h<regions; h++){
		chng += stats[h].drown;
	}
	printf("\t\tchng: %u\n",chng);

    printf("\texposure: %lu\n", stats_t.exposure);
    chng=stats[0].exposure;
    for(h=1; h<regions; h++){
        chng += stats[h].exposure;
    }
    printf("\t\tchng: %u\n",chng);

	printf("\told_age: %lu\n", stats_t.old_age);
	chng=stats[0].old_age;
	for(h=1; h<regions; h++){
		chng += stats[h].old_age;
	}
	printf("\t\tchng: %u\n",chng);

	printf("\tdied_attacking: %lu\n", stats_t.died_attacking);
	chng=stats[0].died_attacking;
	for(h=1; h<regions; h++){
		chng += stats[h].died_attacking;
	}
	printf("\t\tchng: %u\n",chng);

	printf("\tdied_defending: %lu\n", stats_t.died_defending);
	chng=stats[0].died_defending;
	for(h=1; h<regions; h++){
		chng += stats[h].died_defending;
	}
	printf("\t\tchng: %u\n",chng);

	printf("\tnew_life: %lu\n", stats_t.new_life);
	chng=stats[0].new_life;
	for(h=1; h<regions; h++){
		chng += stats[h].new_life;
	}
	printf("\t\tchng: %u\n",chng);

	printf("\tnew_species: %lu\n", stats_t.new_species);
	chng=stats[0].new_species;
	for(h=1; h<regions; h++){
		chng += stats[h].new_species;
	}
	printf("\t\tchng: %u\n",chng);
	printf("Total Living: %u\n", total_living);
    for(h=0; h<regions; h++){
        (void)memset((void *)&stats[h], '\0', sizeof(struct Stats) );
    }

}


void Save_Current_State(uint64_t *year){
	char *filename = (char *)malloc( strlen("BACKUP.lr") + 1);
	(void)strcpy(filename, "BACKUP.lr");
	FILE *fp = fopen(filename, "wb");
    if(!fp){
        printf("Error opening file: %s\n", filename);
        exit(1);
    }
	//struct Stats *stats;
	//struct Species ***life;
	//struct image_attr *ia;
	uint32_t width = ia->width;
	uint32_t height = ia->height;
	uint32_t w = 0, h = 0;
	size_t bytes = 0;

	bytes += fwrite((const void *)&stats_t, sizeof(struct Stats_T), 1, fp);

	for(h=0; h<height; h++){
		for(w=0; w<width; w++){
			bytes += fwrite((const void *)life[h][w], sizeof(struct Species), 1, fp);
		}
	}
	bytes += fwrite((const void *)&ia->cur_sealevel, sizeof(int), 1, fp);
	bytes += fwrite((const void *)&ia->sea_rising, sizeof(int), 1, fp);
	bytes += fwrite((const void *)&ia->cur_temp, sizeof(float), 1, fp);
	bytes += fwrite((const void *)&ia->temp_rising, sizeof(int), 1, fp);
	bytes += fwrite((const void *)year, sizeof(uint64_t), 1, fp);
	bytes += fwrite((const void *)life_speed_up_H, sizeof(char)*height, 1, fp);
	bytes += fwrite((const void *)life_speed_up_W, sizeof(char)*width, 1, fp);
	printf("Saved current state backup!\n");
	printf("bytes wrote: %zu\n\n", bytes);
	free(filename);
	fclose(fp);
}

uint64_t Load_State(void){
    char *filename = (char *)malloc( strlen("BACKUP.lr") + 1);
    (void)strcpy(filename, "BACKUP.lr");
    FILE *fp = fopen(filename, "rb");
    if(!fp){
        printf("Error opening file: %s\n", filename);
        exit(1);
    }
	uint32_t width = ia->width;
	uint32_t height = ia->height;
	uint32_t w = 0, h = 0;
	uint64_t year = 0;
	size_t bytes = 0;

	bytes += fread((void *)&stats_t, sizeof(struct Stats_T), 1, fp);
	for(h=0; h<height; h++){
		for(w=0; w<width; w++){
			bytes += fread((void *)life[h][w], sizeof(struct Species), 1, fp);
		}
	}
	bytes += fread((void *)&ia->cur_sealevel, sizeof(int), 1, fp);
	bytes += fread((void *)&ia->sea_rising, sizeof(int), 1, fp);
	//ia->sea_rising = 0;
	bytes += fread((void *)&ia->cur_temp, sizeof(float), 1, fp);
	bytes += fread((void *)&ia->temp_rising, sizeof(int), 1, fp);
	bytes += fread((void *)&year, sizeof(uint64_t), 1, fp);
	bytes += fread((void *)life_speed_up_H, sizeof(char)*height, 1, fp);
	bytes += fread((void *)life_speed_up_W, sizeof(char)*width, 1, fp);

	printf("bytes read: %zu\n", bytes);
	free(filename);
	fclose(fp);
	return w; //year
}



void World_Thread(void){
	uint64_t year = 1;
	//uint64_t turn_death_total;
	//double turn_life_total;
	size_t height = ia->height;
	size_t width = ia->width;
	struct timeval starttime,endtime;
    static struct timespec ts;
    ts.tv_sec = 0;
    ts.tv_nsec = 10000;
	No_Exit = 1;
	//struct timeval teststart,testend;
	double time1 = 0;
	//int cur_sealevel = 0;
#ifndef LOAD_BACKUP
	const int w = 2200;
	const int h = 900;
	unsigned char rgb[3];
	unsigned int n3 = 0;
#endif
	unsigned int n1 = 0;
	unsigned int n2 = 0;
	unsigned int Tcount = 0;
	unsigned int regions = Threads*2; //evens and odds
	unsigned int thread_step = 0;
	pthread_t *threads_p = (pthread_t *)malloc(sizeof(pthread_t) * (regions+1) );
	unsigned int *t_ids = (unsigned int *)malloc(sizeof(unsigned int) * (regions+1) );

	//pthread_t *threads_di_p = (pthread_t *)malloc(sizeof(pthread_t) * Threads);
	//unsigned int *t_di_ids = (unsigned int *)malloc(sizeof(unsigned int) * Threads);

	//if(thread_step % regions != 0){
	thread_step = floor(height/regions);
	//}
	printf("Threads: %u thread_step: %u regions: %u\n", Threads, thread_step, regions);

	//thread_step 
	// height/3 / Threads*2 : must have all threads active in center of dataset to be efficient early (needs to be sufficiently small)
	//thread_step must be whole number
	//
	/*
	thread_di_i = (struct Thread_I *)malloc( sizeof(struct Thread_I)*Threads);
	for(n1=0; n1<Threads; n1++){
		thread_di_i[n1].start_h = n2;
		thread_di_i[n1].end_h   = (n1+1 != Threads) ? (n1+1)*floor(height/Threads) : height;
		t_di_ids[n1] = n1;
		n2 += floor(height/Threads);
	}
	*/

	n2 = 0;
	thread_i = (struct Thread_I *)malloc( sizeof(struct Thread_I)*regions);
	stats = (struct Stats *)malloc( sizeof(struct Stats) * regions);

	(void)memset((void *)&stats_t, '\0', sizeof(struct Stats_T) );

	for(n1=0; n1<regions; n1++){
		(void)memset((void *)&stats[n1], '\0', sizeof(struct Stats) );
		//stats[n1]

	}
	for(n1=0; n1<regions; n1++){
		thread_i[n1].start_h = n2;
		thread_i[n1].end_h   = (n1+1 != regions) ? (n1+1)*thread_step - 1: height - 1;
		n2 += thread_step;
		printf("start_h: %u end_h: %u\n", thread_i[n1].start_h, thread_i[n1].end_h);
		t_ids[n1] = n1;
		//(void)memset((void *)stats, '\0', sizeof(struct Stats) );
		//stats_t = malloc(sizeof(struct Stats_T));
	}

	//initialize empty life array
	Allocate_Life_Array(height, width);
	printf("Allocated Life array\n");


/////////

	//int Loading_Backup = ;

/////////

#ifdef LOAD_BACKUP
	//if(Loading_Backup){
		year = Load_State();
		Adjust_Sea_Level(1);
		Adjust_Climate(1);
		printf("loaded backup file year: %lu sealevel: %d rising: %d\n", year, ia->cur_sealevel, ia->sea_rising);
	//}else{
#else
	//"plant" first primate tribe [somewhere in africa :)]
	//H 1000 W 2500
		stats_t.total_runtime = 4;
		for(n1=w-5; n1<w+5; n1++){
			for(n2=h-5; n2<h+5; n2++){
				//need to check terrain for water
				if(ia->data[n2][n1] > ia->cur_sealevel){
					life[n2][n1] = (struct Species *)malloc( sizeof(struct Species) );
					Add_First_Life( life[n2][n1] );
					//if(n1==-5)
					Gen_Tribe_Color(life[n2][n1], rgb);
					ia->image[width*n2*3 + n1*3]     = rgb[0];
					ia->image[width*n2*3 + n1*3 + 1] = rgb[1];
					ia->image[width*n2*3 + n1*3 + 2] = rgb[2];
					n3++;
					life_speed_up_H[n2] = 1;
					life_speed_up_W[n1] = 1;
					life[n2][n1]->alive = 1;
				}
			}
		}
		printf("Added %d initial tribes!\n", n3);
		
	//}
#endif

	FM_Alloc(height, width);
	FM_Reset(height, width);


	//launch OpenGL thread
	//Image_Locked = 0;
	//glutInit(&argc,argv);

	sleep(1);

        if (pthread_create(&threads_p[regions], NULL, Run_GL, (void*)&t_ids[regions]) != 0){
            printf("Error: pthread_create failed for thread: opengl !\n");
            exit(1);
        }

	printf("launched opengl thread!\n");
	sleep(1);
	printf("equatorial temp: %f\n", ia->cur_temp);
	printf("sea level: %d\n", ia->cur_sealevel);

	//No_Exit = 1;
	gettimeofday(&starttime, NULL);
	while(No_Exit == 1){
		//start calculating years
		//raise sea level if right multiple (going by 1m per 1000yrs) based on data from past 140yrs for now ...
		//drawls terrain/land into image
		if(year%1000 == 0){ // 1000yrs = 1meter
			//printf("sea level: %d\n", ia->cur_sealevel);
	       // if(Image_Locked)
    	     //   sleep(1);
			//Image_Locked = 1;
			Adjust_Sea_Level(0);
			Adjust_Climate(0);
			//printf("\nsea level: %d\n", ia->cur_sealevel);
			Save_Current_State(&year);
			//printf("Saved current state backup!\n");
			//Image_Locked = 0;
		}

	//gettimeofday(&teststart, NULL);
	//printf("here 4\n");
	//launch odd steps
	for(Tcount = 0; Tcount < regions; Tcount+=2){
		//printf("Tribe %u\n", Tcount);
		if(pthread_create(&threads_p[Tcount], NULL, Tribe_Actions, (void*)&t_ids[Tcount]) != 0){
			printf("Error: pthread_create failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}
	for(Tcount=0; Tcount < regions; Tcount+=2){
		if(pthread_join(threads_p[Tcount], NULL) != 0){
			printf("Error: pthread_join failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}

	//launch even steps
	for(Tcount = 1; Tcount < regions; Tcount+=2){
		//printf("Tribe-e: %u\n", Tcount);
		if (pthread_create(&threads_p[Tcount], NULL, Tribe_Actions, (void*)&t_ids[Tcount]) != 0){
			printf("Error: pthread_create failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}
	for(Tcount=0; Tcount < regions; Tcount+=2){
		if (pthread_join(threads_p[Tcount], NULL) != 0){
			printf("Error: pthread_join failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}
//printf("here 5\n");
	//printf("FM_Reset\n");
	FM_Reset(height, width);
//printf("here 6\n");
		//gettimeofday(&teststart, NULL);
		//Tribe_Actions(ia);
		//gettimeofday(&testend, NULL);
		//time1 = ((double)(testend.tv_sec*1000000-teststart.tv_sec*1000000+testend.tv_usec-teststart.tv_usec))/1000000;
		//printf("Tribe Actions: %lf\n", time1);

		// ^^ initiate actions combat/desease/create_life/migrate/socialize

		//gettimeofday(&teststart, NULL);
		//parse life array and drawl tribes into image



	//gettimeofday(&teststart, NULL);
		//Drawl_Image();

/*
	if(year % 5 == 0){
		//if(Image_Locked)
		//	sleep(1);

		//while(Image_Locked){
		//	nanosleep (&ts, NULL);
		//}
		//Image_Locked = 1;
		//Gen_Detailed_Counts(year);
		for(Tcount = 0; Tcount < Threads; Tcount++){
			//printf("Drawl Image %u\n", Tcount);
			if(pthread_create(&threads_di_p[Tcount], NULL, Drawl_Image, (void *)&t_di_ids[Tcount]) != 0){
				printf("Error: pthread_create failed for thread: %d (Drawl_Image) !\n", Tcount);
				exit(1);
			}
		}
		for(Tcount=0; Tcount < Threads; Tcount++){
			if(pthread_join(threads_di_p[Tcount], NULL) != 0){
				printf("Error: pthread_join failed for thread: %d (Drawl_Image) !\n", Tcount);
				exit(1);
			}
		}
		//Image_Locked = 0;
	}
*/
	//(void)LoadTexture();
	//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ia->width, ia->height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)ia->image);
    //glBindTexture( GL_TEXTURE_2D, Image_Texture );
    //glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    //glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

	//gettimeofday(&testend, NULL);
	//time1 = ((double)(testend.tv_sec*1000000-teststart.tv_sec*1000000+testend.tv_usec-teststart.tv_usec))/1000000;
	//printf("Drawl_Image: %lf\n", time1);

	//Gen_Detailed_Counts();



		//printf("drew image\n");
		//gettimeofday(&testend, NULL);
		//printf("Drawl_Image(: %lf\n", time1);


		//gettimeofday(&teststart, NULL);
		//increment year
		year++;
		//print seconds/year every 10yrs 

		if(year%1000 == 0){

			//Gen_Detailed_Counts(year, regions);
			//for(n1=0; n1<regions; n1++){
			//	(void)memset((void *)&stats[n1], '\0', sizeof(struct Stats) );
			//}

			gettimeofday(&endtime, NULL);
			time1 = ((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
			stats_t.total_runtime += time1;
			Gen_Detailed_Counts(year, regions);
			//printf("Current: sea level %d\n", ia->cur_sealevel);
			if(ia->sea_rising)
				printf("Current: Sec/Year %fs cur_sealevel %dm rising +1m/1Kyears", (float)time1/1000, ia->cur_sealevel);
			else
				printf("Current: Sec/Year %fs cur_sealevel %dm falling -1m/1Kyears", (float)time1/1000, ia->cur_sealevel);

			printf(" equatorial mean temp: %.02fc changing: %.02fc/1Kyears\n", ia->cur_temp, (ia->temp_rising ? 0.2 : -0.2) );
			printf("Total: Runtime %.02lf hrs Avg Sec/Year %lfs\n", (double)stats_t.total_runtime/60/60, (double)stats_t.total_runtime/year);
			
			gettimeofday(&starttime, NULL);
			//Save_Current_State(year);
			//printf("Saved current state backup!\n");
			//Adjust_Sea_Level();
		}
/*

		if(year%1000 == 0){
			gettimeofday(&endtime, NULL);
			time1 = ((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
			printf("\nYear: %lu Sec/Year: %lf\n", year, time1/1000);
			printf("sealevel: %u\n", ia->cur_sealevel);
			gettimeofday(&starttime, NULL);
			//process stats
			printf("deaths\n");
			printf("disease: %u drown: %u old_age: %u died_attacking: %u died_defending: %u\n",  stats.disease, stats.drown, stats.old_age, stats.died_attacking, stats.died_defending);
			turn_death_total = stats.disease + stats.drown + stats.old_age + stats.died_attacking + stats.died_defending;
			printf("\tsubtotal: %lu\n", turn_death_total);
			printf("life\n");
			printf("new_life: %u new_species: %u\n", stats.new_life, stats.new_species);
			turn_life_total = stats.new_life - turn_death_total;
			printf("\tnet subtotal: %.00lf\n", turn_life_total);

			printf("Totals:\n");
			stats.t_disease += stats.disease;
			stats.t_drown += stats.drown;
			stats.t_old_age += stats.old_age;
			stats.t_died_attacking += stats.died_attacking;
			stats.t_died_defending += stats.died_defending;
			stats.t_new_life += stats.new_life;
			stats.t_new_species += stats.new_species;
			//t_species_extinct;
			printf("\tdisease: %lu\n", stats.t_disease);
			printf("\tdrown: %lu\n", stats.t_drown);
			printf("\told_age: %lu\n", stats.t_old_age);
			printf("\tdied_attacking: %lu\n", stats.t_died_attacking);
			printf("\tdied_defending: %lu\n", stats.t_died_defending);
			printf("\tnew_life: %lu\n", stats.t_new_life);
			printf("\tnew_species: %lu\n", stats.t_new_species);

			stats.disease = 0;
			stats.drown = 0;
			stats.old_age = 0;
			stats.died_attacking = 0;
			stats.died_defending = 0;
			stats.new_life = 0;
			stats.new_species = 0;

		}
*/
	}
	//printf("here\n");
	if(No_Exit == 0){
		Gen_Detailed_Counts(year, regions);
		Save_Current_State(&year);
		printf("State saved!\n");
	}
	//if(year == 5)
	//	exit(1);

        if (pthread_join(threads_p[regions], NULL) != 0){
            printf("Error: pthread_join failed for thread: %d !\n", regions);
            exit(1);
        }
        //if (pthread_create(&threads_p[regions], NULL, Run_GL, (void*)&t_ids[regions]) != 0){
        //    printf("Error: pthread_create failed for thread: opengl !\n");
        //    exit(1);
       // }

		free(ia->image);
		for(n1=0; n1<height; n1++){
			free(ia->data[n1]); //= (int16_t *)malloc(sizeof(int16_t)*width);
		}
		free(ia->data);
		free(ia);
		free(threads_p);
		free(t_ids);
		free(thread_i);
		for(n1=0; n1<height; n1++){
			for(n2=0; n2<width; n2++){
				free(life[n1][n2]);
			}
			free(life[n1]);
		}
		free(life);
		free(life_speed_up_H);
		free(life_speed_up_W);
		for(n1=0; n1<height; n1++){
			//for(n2=0; n2<width; n2++){
			//	free(fought[n1][n2]);
			//	free(mated[n1][n2]);
			//}
			free(fought[n1]);
			free(mated[n1]);
		}
		free(fought);
		free(mated);
		free(stats);
}