#include "Life.h"

struct Species ***life;
struct Stats stats;
struct Surround_FM fm;

//char **fought;
//char **mated;

/*
unsigned char Dna_Step(unsigned char num){
	//0 - 51
	unsigned char deviation = 0;

	//make num a multiple of 5 without going over 255 or under 0 in as few steps as possible ...
	if(num % 5 == 0)
		 

	//return multiple

	return(num+deviation / 5);
}
*/

void Allocate_Life_Array(size_t height, size_t width){
	size_t n1, n2;
	life = (struct Species ***)malloc(sizeof(struct Species **) * height);
	for(n1=0; n1<height; n1++){
		life[n1] = (struct Species **)malloc(sizeof(struct Species *) * width);
	}
	for(n1=0; n1<height; n1++){
		for(n2=0; n2<width; n2++){
			life[n1][n2] = NULL;
		}
	}
	//Make stats initialized to 0
	(void)memset( (void *)&stats, '\0', sizeof(struct Stats) );

	return;
}

void Gen_Tribe_Color(struct Species *one, unsigned char *rgb){
	// 6751269 possibilities based on species/traits
	rgb[0] = floor(one->intelligence/4) + floor(one->temp_l/4) + floor(one->social_factor/4);
	rgb[1] = floor(one->strength/4) + floor(one->temp_h/4) + floor(one->fight_flight_balance/4);
	rgb[2] = floor(one->speed/4) + floor(one->max_age/4) + floor(one->migration_factor/4);
	//one->intelligence
	//one->strength
	//one->speed

}

int Is_Same_Species(struct Species *one, struct Species *two){
	// "dna" determined by all variables, no one variable can deviate more than 4
	//better to implement steps instead ie: 0-3 4-7 8-11 etc.  4*(0->63)+(0->4)
	// y=mx+b   y range 0-255,  if x = x same species, b == subspecies deviation
	//must allow for subspecies deviation

	//unsigned char x = floor(num/4);
	//b = 255%4 * 4;
	if(one == NULL || two == NULL)
		return 0;

	if( floor(one->intelligence/4) != floor(two->intelligence/4) )
		return 0;
	if( floor(one->strength/4) != floor(two->strength/4) )
		return 0;
	if( floor(one->speed/4) != floor(two->speed/4) )
		return 0;
	if( floor(one->temp_l/4) != floor(two->temp_l/4) )
		return 0;
	if( floor(one->temp_h/4) != floor(two->temp_h/4) )
		return 0;
	if( floor(one->max_age/4) != floor(two->max_age/4) )
		return 0;
	if( floor(one->reproductive_rate/4) != floor(two->reproductive_rate/4) )
		return 0;

	return 1;
}

void Add_First_Life(struct Species *one){
	one->intelligence = 16;
	one->strength = 16;
	one->speed = 16;
	one->imunity = 127;
	one->temp_l = 28;
	one->temp_h = 32;
	one->reproductive_rate = 1;
	one->fight_flight_balance = 127;
	one->migration_factor = 8;
	one->social_factor = 8;
	one->max_age = 36;
	one->cur_age = 0;
	//one->fought = 0;
	//one->mated = 0;
}

void Create_Life(struct Species *one, struct Species *two, struct Species *three){
	//mix sub species 1 and 2 to create 3 (average of 1 and 2) [ ~8.3% chance of (+/-1pt) species deviation ]
	//chance of new species:  ~1% 
	int rand1;
	int use_ceil = 0;
	double tmp;
	struct timeval cur;
	gettimeofday(&cur, NULL);
	srand ( (unsigned int)cur.tv_usec );
	rand1 = rand() % 100 + 1;
	if(rand1 > 49)
		use_ceil = 1;

	//add typecasts for unsigned char ...

	tmp = (one->intelligence + two->intelligence) / 2;
	three->intelligence = (unsigned char)( use_ceil ? ceil(tmp) : floor(tmp) );
	tmp = (one->strength + two->strength) / 2;
	three->strength = (unsigned char)( use_ceil ? ceil(tmp) : floor(tmp) );
	tmp = (one->speed + two->speed) / 2;
	three->speed = (unsigned char)( use_ceil ? ceil(tmp) : floor(tmp) );

	//keep within ranges
	tmp = (one->temp_l + two->temp_l) / 2;
	three->temp_l = (unsigned char)( use_ceil ? ceil(tmp) : floor(tmp) );
	tmp = (one->temp_h + two->temp_h) / 2;
	three->temp_h = (unsigned char)( use_ceil ? ceil(tmp) : floor(tmp) );

	//
	tmp = (one->max_age + two->max_age) / 2;
	three->max_age = (unsigned char)( use_ceil ? ceil(tmp) : floor(tmp) );

	//fixed to 1 for now
	three->reproductive_rate = 1;
	//three->reproductive_rate = (one->reproductive_rate+two->reproductive_rate)/2
	//starts at 0yrs old
	three->cur_age = 0;
	
	//suseconds_t signed integer type capable of storing values at least in the range [-1, 1000000].
	//srand ( (unsigned int)cur.tv_usec );
	rand1 = rand() % 12;
	//1/12 chance we do a deviation
	if(rand1 == 6){
		//do deviation
		//int new_species = 0;
		char deviation = rand() % 100 + 1;
		//+1 deviation, otherwise -1
		if(deviation > 49)
			deviation = 1;
		else
			deviation = -1;
		rand1 = rand() % 5; //which feild will be modified
		//1/4 chance the selected feild is at an upper/lower limit
		//1/2 chance deviation is the +1/-1 needed to create new species
		if(rand1 == 0){
			three->intelligence += deviation;
		}else if(rand1 == 1){
			three->strength += deviation;
		}else if(rand1 == 2){
			three->speed += deviation;
		}else if(rand1 == 3){
			three->temp_l += deviation;
			three->temp_h -= deviation;
		}else{
			//stays within range 30 - 128yrs
			if(deviation && three->max_age < 128)
				three->max_age += 1;
			if(!deviation && three->max_age > 30)
				three->max_age -= 1;
		}
		//was this a new species or just subspecies
		//1/96 overall chance any new life is a new species
		if( !Is_Same_Species(one, three) ){
			//printf("New species created!\n");
			stats.new_species++;
		}
	}

}

static int Tribe_Migrate(struct image_attr *ia, unsigned int src_y, unsigned int src_x, unsigned int *dest){
	//return 1 if moved
	//put new location in 

	unsigned int n1, n2;
	struct Moves{unsigned int x; unsigned int y; unsigned int valid; int rating;}moves[4];

	//FIX!
	//if any of these are greater/less than height or width they need to be set to 0
	//same goes for all neighbors calculations

	//4 potential destination initialization
	moves[0].x = src_x-1; 
	moves[0].y = src_y;
	moves[0].valid  = 1;
	moves[0].rating = 4;
	moves[1].x = src_x+1;
	moves[1].y = src_y;
	moves[1].valid  = 1;
	moves[1].rating = 4;
	moves[2].x = src_x;
	moves[2].y = src_y-1;
	moves[2].valid  = 1;
	moves[2].rating = 4;
	moves[3].x = src_x;
	moves[3].y = src_y+1;
	moves[3].valid  = 1;
	moves[3].rating = 4;

	//4 neighors of a move destination
	struct Neighbors{unsigned int x; unsigned int y;}neighbors[4];

	//to store candidate destination with highest rating
	struct Dest_Cand{int h_rating; unsigned int m_index;}dest_cand;
	int cand_ties[4];

    struct timeval cur;
    int rand1;


	for(n1=0; n1<4; n1++){
		//rule out moving to water
		if(ia->cur_sealevel >= ia->data[moves[n1].y][moves[n1].x]){
			moves[n1].valid = 0;
			continue;
		}
		//rule out moving to occupied coordinates
		if(life[moves[n1].y][moves[n1].x] != NULL)
			moves[n1].valid = 0;
	}
	for(n1=0; n1<4; n1++){
		//if all ruled out return 0;
		if(moves[n1].valid == 1)
			break;
		if(n1 == 3)
			return 0;
	}
	//calculate ratings for valid destinations
	for(n1=0; n1<4; n1++){
		if(!moves[n1].valid)
			continue;
		//initialize neighbors for this potential move
		neighbors[0].x = moves[n1].x-1;
		neighbors[0].y = moves[n1].y;
		neighbors[1].x = moves[n1].x+1;
		neighbors[1].y = moves[n1].y;
		neighbors[2].x = moves[n1].x;
		neighbors[2].y = moves[n1].y-1;
		neighbors[3].x = moves[n1].x;
		neighbors[3].y = moves[n1].y+1;
		//calculate rating for this move threat/reward
		for(n2=0; n2<4; n2++){
			if(neighbors[n2].y == src_y){  //if a neighbor is src_x/src_y don't count self
				if(neighbors[n2].x == src_x)
					continue;
			}
			//if neighbor is empty terrain don't count
			if(life[neighbors[n2].y][neighbors[n2].x] == NULL)
				continue;

			//if neighbor is different species dec rating
			if(!Is_Same_Species(life[src_y][src_x], life[neighbors[n2].y][neighbors[n2].x]) ){
				moves[n1].rating--;
				continue;
			}
			//if neighbor is same inc rating
			moves[n1].rating++;
		}
	}
	dest_cand.h_rating = -1;
	//find destination with highest rating
	for(n1=0; n1<4; n1++){
		if(!moves[n1].valid){
			moves[n1].rating = 0;
			continue;
		}
		if(	moves[n1].rating > dest_cand.h_rating){
			dest_cand.h_rating = moves[n1].rating;
			dest_cand.m_index  = n1;
		} 

	}
	n2=0;
	//if rating tie should pick a random choice out of them
	//count rating ties
	for(n1=0; n1<4; n1++)
		cand_ties[n1] = 0;
	for(n1=0; n1<4; n1++){
		if(!moves[n1].valid)
			continue;
		if(dest_cand.h_rating == moves[n1].rating){
			cand_ties[n1] = 1;
			n2++;
		}//else{
		//	cand_ties[n1] = 0;
		//}
	}
	if(n2){ //was no tie
		dest[0] = moves[dest_cand.m_index].y;
		dest[1] = moves[dest_cand.m_index].x;
	}
	if(n2 > 1){ //was a tie
		//n2 can be  2  3  or 4
		gettimeofday(&cur, NULL);
    	srand ( (unsigned int)cur.tv_usec );
		rand1 = rand() %  n2 + 1; // 1 to 2, 1 to 3, or 1 to 4
		for(n1=0; n1<4; n1++){
			if(!cand_ties[n1])
				continue;
			//n2++;
			if(n2 == rand1){
				//moves[n1] is dest choice
				dest[0] = moves[n1].y;
				dest[1] = moves[n1].x;
				break;
			}
			n2++;
		}
	}

	if(ia->cur_sealevel < ia->data[dest[0]][dest[1]]){
		//Move to destination
		life[dest[0]][dest[1]] = malloc(sizeof(struct Species));
		(void)memcpy(life[dest[0]][dest[1]], (const void *)life[src_y][src_x], sizeof(struct Species));
		free(life[src_y][src_x]);
		life[src_y][src_x] = NULL;
		return 1;
	}
	return 0;
}

static int Fight_Tribe(struct Species *one, struct Species *two){
	//simulate outcome of a potential combat between these two tribes
	// return 1 *one won, 0 *one lost
	int rand1, rand2;
	struct timeval cur;
	gettimeofday(&cur, NULL);
	srand ( (unsigned int)cur.tv_usec );

	//fight determined by  1 part strength, 1 part speed, 2 parts intelligence, and 1 part chance
	rand1 = rand() % 256;
	rand2 = rand() % 256;
	unsigned int rating1 = one->intelligence*2 + one->strength + one->speed + rand1;
	unsigned int rating2 = two->intelligence*2 + two->strength + two->speed + rand2;
	//cur_age ?
	// 1 in 256 chance they are equal
	if(rating1 > rating2)
		return 1;
	if(rating2 > rating1)
		return 0;
	//equal
	while(rand1 == rand2){
		rand1 = rand() % 256;
		rand2 = rand() % 256;
	}
	return rand1>rand2 ? 1 : 0;
}

static void Tribe_Interactions(unsigned int src_y, unsigned int src_x){
	//evaluate all surrounding tribes for threat/reward take proper actions
	unsigned int n1, n2, n3;
	//int index;
	//char chosen[4];
	int rand1, rand2, rand3;
	int out_come;
	struct timeval cur;
	struct Neighbors{unsigned int y; unsigned int x; unsigned int occupied;}neighbors[4];
	struct Neighbors_T{unsigned int y; unsigned int x;}tmp[4];
	


	gettimeofday(&cur, NULL);
	srand ( (unsigned int)cur.tv_usec );
	//rand1 = rand() % 24;  // 0 to 23

	//need to be randomly assigned, 24 possible permutations of the 4 structures ?
	//n×(n - 1)×(n - 2)×...×2×1


	//FIX! for map wrap

	tmp[0].y = src_y;
	tmp[0].x = src_x - 1;
	//tmp[0].occupied = 0;

	tmp[1].y = src_y;
	tmp[1].x = src_x + 1;
	//tmp[1].occupied = 0;

	tmp[2].y = src_y - 1;
	tmp[2].x = src_x;
	//tmp[2].occupied = 0;

	tmp[3].y = src_y + 1;
	tmp[3].x = src_x;
	//tmp[3].occupied = 0;


	//mix them randomly
	rand1 = rand() % 4;  //pick of any
	rand2 = rand() % 3;  //pick of remaining 3
	rand3 = rand() % 2;  //pick of remaining 2

	neighbors[0].y = tmp[rand1].y;
	neighbors[0].x = tmp[rand1].x;
	neighbors[0].occupied = 0;
	n2 = 0;
	for(n1=0; n1<4; n1++){ //pick second one randomly out of 3 remaining
		if(n1 != rand1){ //if not already taken
			if(n2 == rand2){
				neighbors[1].y = tmp[n1].y;
				neighbors[1].x = tmp[n1].x;
				neighbors[1].occupied = 0;
				break;
			}
			n2++;
		}
	}
	n3 = 0;
	for(n2=0; n2<4; n2++){ //pick third one
		if(n2 != rand1){
			if(n2 != n1){
				if(n3 == rand3){
					neighbors[2].y = tmp[n2].y;
					neighbors[2].x = tmp[n2].x;
					neighbors[2].occupied = 0;
					break;
				}
				n3++;
			}
		}
	}

	for(n3=0; n3<4; n3++){ //last one is the remaining 
		if(n3 != rand1){
			if(n3 != n1){
				if(n3 != n2){
					neighbors[3].y = tmp[n3].y;
					neighbors[3].x = tmp[n3].x;
					neighbors[3].occupied = 0;
					break;
				}
			}
		}
	}

	for(n1=0; n1<4; n1++){
		if(life[neighbors[n1].y][neighbors[n1].x] != NULL){
			neighbors[n1].occupied = 1;
		}
	}

	for(n1=0; n1<4; n1++){
		if(neighbors[n1].occupied){
			if( Is_Same_Species(life[src_y][src_x], life[neighbors[n1].y][neighbors[n1].x]) ){
				//social_factor see if we'll mate/fight/nothing
				rand1 = rand() % (life[src_y][src_x]->social_factor+1) + 1;
				rand2 = rand() % (life[src_y][src_x]->social_factor+1) + 1;
				//1/1 chance of no mating if social_factor 0  1/256 if 255,  1 / 1*(IM+1)
				if(rand1 == rand2){//no mating
					if(fought[src_y][src_x]) //no fighting if already fought
						continue;
					//analyse fight_flight to see if we fight them
					rand1 = rand() % (life[src_y][src_x]->fight_flight_balance+1) + 1;
					rand2 = rand() % (life[src_y][src_x]->fight_flight_balance+1) + 1;
					//1/1 chance of attacking if fight_flight 0  1/256 if 255,  1 / 1*(IM+1)
					//0 = never attack  255 = 255/256 attack chance
					if(rand1 != rand2){//attacking
						fought[src_y][src_x] = 1;
						out_come = Fight_Tribe( (struct Species *)life[src_y][src_x], (struct Species *)life[neighbors[n1].y][neighbors[n1].x] );
						if(out_come){//if the fight was won
							free(life[neighbors[n1].y][neighbors[n1].x]);
							life[neighbors[n1].y][neighbors[n1].x] = NULL;
							stats.died_defending++;
							//printf("tribe attacked and killed!\n");
							if(life[src_y][src_x]->imunity < 255)
								life[src_y][src_x]->imunity++;
						}
						if(!out_come){ //died
							free(life[src_y][src_x]);
							life[src_y][src_x] = NULL;
							stats.died_attacking++;
							//printf("tribe killed attacking!\n");
							if(life[neighbors[n1].y][neighbors[n1].x]->imunity < 255)
								life[neighbors[n1].y][neighbors[n1].x]->imunity++;
							return;
						}
					}
				}else{ //are mating
					if(mated[src_y][src_x]){
						 if(mated[neighbors[n1].y][neighbors[n1].x]){
							continue;
						}
					}
					//mating = 1;
					out_come = 1;
					//choose open space for offspring
					for(n2=0; n2<4; n2++){
						if(neighbors[n2].occupied == 0)
							break;
						if(n2 == 3)
							out_come = 0;
					}
					//choose random open space if multiple

					//


					//if space available create life
					if(out_come){
							mated[src_y][src_x] = 1;
							mated[neighbors[n1].y][neighbors[n1].x] = 1;
							life[neighbors[n2].y][neighbors[n2].x] = malloc( sizeof(struct Species) );
							Create_Life(life[src_y][src_x], life[neighbors[n1].y][neighbors[n1].x], life[neighbors[n2].y][neighbors[n2].x]);
							//printf("Created new life!\n");
							stats.new_life++;
							if(life[src_y][src_x]->imunity < 255)
								life[src_y][src_x]->imunity++;
							if(life[neighbors[n1].y][neighbors[n1].x]->imunity < 255)
								life[neighbors[n1].y][neighbors[n1].x]->imunity++;
					}
				}
			}else if(!fought[src_y][src_x]){ //havn't already fought
				//fight_flight_balance see if we'll fight(attack)
				rand1 = rand() % (life[src_y][src_x]->fight_flight_balance+1) + 1;
				rand2 = rand() % (life[src_y][src_x]->fight_flight_balance+1) + 1;
				if(rand1 != rand2){//attacking
					fought[src_y][src_x] = 1;
					out_come = Fight_Tribe( (struct Species *)life[src_y][src_x], (struct Species *)life[neighbors[n1].y][neighbors[n1].x] );
					if(out_come){//fight was won
						free(life[neighbors[n1].y][neighbors[n1].x]);
						life[neighbors[n1].y][neighbors[n1].x] = NULL;
						stats.died_defending++;
						//printf("tribe attacked and killed!\n");
						if(life[src_y][src_x]->imunity < 255)
							life[src_y][src_x]->imunity++;
					}
					if(!out_come){ //died
						free(life[src_y][src_x]);
						life[src_y][src_x] = NULL;
						stats.died_attacking++;
						//printf("tribe killed attacking!\n");
						if(life[neighbors[n1].y][neighbors[n1].x]->imunity < 255)
							life[neighbors[n1].y][neighbors[n1].x]->imunity++;
						return;
					}
				}
			}
			//if(life[src_y][src_x]->fought){
			//	if(life[src_y][src_x]->mated){
			//		return;
			//	}
			//}
		}
		if(fought[src_y][src_x]){
			if(mated[src_y][src_x]){
				return;
			}
		}
	}
}

/*
void FM_Alloc(unsigned int height, unsigned int width){
	unsigned int h;
	fought = (char **)malloc(sizeof(char *)*height);
	for(h=0; h<height; h++)
		fought[h] = (char *)malloc(sizeof(char)*width);
	mated = (char **)malloc(sizeof(char *)*height);
	for(h=0; h<height; h++)
		mated[h] = (char *)malloc(sizeof(char)*width);
}
*/

//static void FM_Reset(unsigned int height, unsigned int width){
	//unsigned int h;
	//unsigned int w;
	//for(h=0; h<height; h++){
	//	for(w=0; w<width; w++){
	//		//if(life[h][w] != NULL){
	//		fought[h][w] = 0;
	//		mated[h][w] = 0;
			//}
	//	}
	//}
	//(void)memset( (void *)fought, '\0', sizeof(char)*width*height);
	//(void)memset( (void *)mated, '\0', sizeof(char)*width*height);
	//}
	//free(fought);
	//free(mated);
	//FM_Alloc(height, width);

//}

void Tribe_Actions(struct image_attr *ia){
	//initiate actions migrate/combat/desease/create_life/migrate/socialize
	int n1, n2;
	unsigned int y;
	unsigned int x;
	unsigned int height = ia->height;
	unsigned int width = ia->width;
	//struct Moves{unsigned int y; unsigned int x;}moves[4];
	//struct Spots dest;
	unsigned int dest[] = {0, 0}; //y x
	//unsigned int valid_moves[5];
	//unsigned int good_l[4];
	//unsigned int gl_tmp = 0;
	//unsigned int highest_gl = 0;
	char did_move = 0;
	//unsigned int moves[] = {-1, 1};
	//unsigned int moves_y[] = {-1, 0, 1};
	//struct spots{unsigned int x; unsigned int y;}surrounding[4];
	//unsigned int cur_x, cur_y;
	//unsigned int pot_x, pot_y;
	//unsigned int num1, num2;
	struct timeval cur;
    int rand1, rand2;
	int cur_sealevel = ia->cur_sealevel;
	int Tcount;
	const int Threads = 4;
	pthread_t *Threads = (pthread_t *)malloc(sizeof(pthread_t) * Threads);

	gettimeofday(&cur, NULL);
	srand ( (unsigned int)cur.tv_usec );

	//FM_Alloce(height, width);

	//char **mated;
	//char **fought;
	//mated = malloc(sizeof(char *)*3);
	struct FM_Info *fm_info = (struct FM_Info *)malloc( sizeof(struct FM_Info) * Threads * 2);

	for(y=0; y<(Threads * 2); y++){
		fm_info[y].mated = (char *)malloc(sizeof(char)*width);
		(void)memset( (void *)fm_info[y].mated, '\0', sizeof(char)*width);
	}
	//fought = malloc(sizeof(char *)*3);
	for(y=0; y<(Threads * 2); y++){
		fm_info[y].fought = (char *)malloc(sizeof(char)*width);
		(void)memset( (void *)fm_info[y].fought, '\0', sizeof(char)*width);
	}

	

	for(y=0; y<height; y++){
		for(x=0; x<width; x++){
			if(life[y][x] != NULL){ //if there is life at this location
				//get one year older
				life[y][x]->cur_age++;
				//die from old age?
				if(life[y][x]->cur_age == life[y][x]->max_age ){
					free(life[y][x]);
					life[y][x] = NULL;
					stats.old_age++;
					//printf("tribe died from old age!\n");
					continue;
				}
				//die from disease:  1/1 chance of death if imunity 0  1/256 if 255,  1 / 1*(IM+1)
				rand1 = rand() % (life[y][x]->imunity+1) + 1;
				rand2 = rand() % (life[y][x]->imunity+1) + 1;
				if(rand1 == rand2){
					free(life[y][x]);
					life[y][x] = NULL;
					stats.disease++;
					//printf("tribe died from disease!\n");
					continue;
				}
				//migrate: 0 = never move  255 = move everychance
				rand1 = rand() % (life[y][x]->migration_factor+1) + 1;
				rand2 = rand() % (life[y][x]->migration_factor+1) + 1;
				if(rand1 == rand2){
					//this tribe won't/can't migrate regardless 
					if(cur_sealevel > ia->data[y][x]){ //drown
						free(life[y][x]);
						life[y][x] = NULL;
						stats.drown++;
						//printf("tribe drown!\n");
						continue;
					}
					did_move = 0; //didn't move lived
				}else{
					//this tribe will move, if it can.
					//analyse surrounding terrain/life (4 coordinates) of potential movements (5 coordinates)
					did_move = Tribe_Migrate(ia, y, x, dest);
				}
			}
		}
	}

	//TEMPORARY: this is not fully optimal, as center ranges will take longer initially (where life starts)



	//launch odd Tribe_Interactions threads
	for(Tcount = 0; Tcount < Threads; Tcount++){
		//calculate row_start
		fm_info[Tcount].row_start = height / Threads * 2 * (Tcount+1);
		fm_info[Tcount].row_end = height / Threads * 2 * (Tcount+2);
		//fm_info is all zero here
		if (pthread_create(&Threads[Tcount], NULL, Tribe_Interactions, &fm_info[Tcount]) != 0){
			printf("Error: pthread_create failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}
	for(Tcount=0; Tcount<Threads; Tcount++){
		if (pthread_join(Threads[Tcount], NULL) != 0){
			printf("Error: pthread_join failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}
	//launch even Tribe_Interactions threads
	for(Tcount = 0; Tcount < Threads; Tcount++){
		fm_info[Tcount+4].row_start = height / Threads * 2 * Tcount;
		fm_info[Tcount+4].row_end = height / Threads * 2 * (Tcount+1);
		//fm_info will be usefull here
		if (pthread_create(&Threads[Tcount], NULL, Tribe_Interactions, &fm_info[Tcount+4]) != 0){
			printf("Error: pthread_create failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}
	for(Tcount=0; Tcount<Threads; Tcount++){
		if (pthread_join(Threads[Tcount], NULL) != 0){
			printf("Error: pthread_join failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}





				if(did_move){
					Tribe_Interactions(dest[0], dest[1]);
					//shouldn't have moved onto water
				}else{
					if(cur_sealevel > ia->data[y][x]){
						free(life[y][x]);
						life[y][x] = NULL;
						stats.drown++;
						//printf("tribe drown!\n");
						continue;
					}
					Tribe_Interactions(y, x);

				}
			}//end of if life != NULL
		}
		//
		//if y = 0  save last line for future ...
		//if y = (height - 2) load that last line ...
		//
		//2 becomes 1
		(void)memcpy(mated[n1], );
		//1 becomes 0
		(void)memcpy(mated[n1], );

		(void)memset( (void *)fought[n1], '\0', sizeof(char)*width);
		(void)memset( (void *)mated[n1], '\0', sizeof(char)*width);
	}
}

void Drawl_Image(struct image_attr *ia){
	//write out ia->image from all data
	unsigned int n1, n2;
	unsigned int height = ia->height;
	unsigned int width  = ia->width;
	int sealevel = ia->cur_sealevel;
	unsigned char rgb[3];

	//drawl land/water first
	for(n1=0; n1<height; n1++){
		for(n2=0; n2<width; n2++){
			if(ia->data[n1][n2] < sealevel){
				rgb[0] = 0;
				rgb[1] = 0;
				rgb[2] = 255;
			}else{
				rgb[0] = 0;
				rgb[1] = 255;
				rgb[2] = 0;
			}
			ia->image[n1*width*3+(n2*3)]   = rgb[0];
			ia->image[n1*width*3+(n2*3+1)] = rgb[1];
			ia->image[n1*width*3+(n2*3+2)] = rgb[2];
		}
	}
	//drawl tribes
	for(n1=0; n1<height; n1++){
		for(n2=0; n2<width; n2++){
			if(life[n1][n2] != NULL){
				//need color generator function instead
				//rgb[0] = life[n1][n2]->intelligence;
				//rgb[1] = life[n1][n2]->strength;
				//rgb[2] = life[n1][n2]->speed;
				Gen_Tribe_Color(life[n1][n2], rgb);
				ia->image[n1*width*3+(n2*3)]   = rgb[0];
				ia->image[n1*width*3+(n2*3+1)] = rgb[1];
				ia->image[n1*width*3+(n2*3+2)] = rgb[2];
			}
		}
	}
}
