/*
    Living Realms is a primate evolution simulator.
    Copyright (C) 2011  Sterling Pickens

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "Life.h"

void KILL_Tribe(uint32_t y, uint32_t x){
	//life[y][x]->alive = 0;
	SET_ZERO(Alive, y, x);
	SET_ZERO(Fought, y, x);
	SET_ZERO(Mated, y, x);
	//fought[y][x] = 0;
	//mated[y][x] = 0;
	//stats_t.total_living--;
}

/*
int Is_Alive(uint32_t src_y, uint32_t src_x){
    if( Alive[src_y][src_x/8] & (1 << (src_x % 8)) )
        return 1;
    return 0;
}

int Has_Mated(uint32_t src_y, uint32_t src_x){
	if( Mated[src_y][src_x/8] & (1 << (src_x % 8)) )
		return 1;
	return 0;
}

int Has_Fought(uint32_t src_y, uint32_t src_x){
	if( Fought[src_y][src_x/8] & (1 << (src_x % 8)) )
		return 1;
	return 0;
}
*/

void Allocate_Life_Array(void){
	uint32_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(n2=0; n2<WIDTH; n2++){
			life[n1][n2] = (struct Species *)malloc(sizeof(struct Species));
			(void)memset( (void *)life[n1][n2], '\0', sizeof(struct Species) );
		}
	}
}

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

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( one->intelligence/4 != two->intelligence/4 )
		return 0;
	if( one->strength/4 != two->strength/4 )
		return 0;
	if( one->speed/4 != two->speed/4 )
		return 0;
	if( one->temp_l/4 != two->temp_l/4 )
		return 0;
	if( one->temp_h/4 != two->temp_h/4 )
		return 0;
	if( one->max_age/4 != two->max_age/4 )
		return 0;
	//if( floor((double)one->reproductive_rate/4) != floor((double)two->reproductive_rate/4) )
	//	return 0;

	return 1;
}

void Add_First_Life(struct Species *one){
	//one->alive = 1;
	one->intelligence          = INTELLIGENCE;
	one->strength              = STRENGTH;
	one->speed                 = SPEED;
	one->imunity               = IMUNITY;
	one->temp_l                = TEMP_L;
	one->temp_h                = TEMP_H;
	//one->reproductive_rate     = REPRODUCTIVE_RATE;
	one->max_age               = MAX_AGE;
	one->cur_age               = CUR_AGE;
	one->fight_flight_balance  = FIGHT_FLIGHT_BALANCE;
	one->interspecies_violence = INTERSPECIES_VIOLENCE;
	one->migration_factor      = MIGRATION_FACTOR;
	one->social_factor         = SOCIAL_FACTOR;
	//one->water_turns           = 0;
	//one->water_direction       = 0;
}

float Location_Temp(uint32_t src_y, uint32_t src_x){
	//return temperature at any given src_y src_x
	float location_temp = (float)stats_t.cur_temp;
	float equator_dist = 0;

	//bordering water, degrees cooler maybe

	//elevation effect
	if(ia->dem[src_y][src_x] < 11001){
		location_temp -= TEMP_PER_1000M*((float)(ia->dem[src_y][src_x]-stats_t.cur_sealevel)/1000);
	}
		//else{
		//location_temp -= TEMP_11K_TO_20K;
	//}
	//dealing with 1/12th scale of 30 arc-second grid
	//1 arc minute = 1/60 of 1deg
	//30 arc-second = 1/30 of 1deg
	//1px = 12x 30 arc-second  = 2/5 of 1deg
	//1800px = 90-0-90  900px is equator

	//equatorial distance effect
	equator_dist = abs( (float)src_y - (float)HEIGHT/2 ) * 2 / 5;  //degrees from equator

	//45c different between eq and poles  .5C per 1deg  hmmmm
	location_temp -= equator_dist / DEM_SCALE;

	return location_temp;
}

int Climate_Fatal(struct Species *one, uint32_t src_y, uint32_t src_x){
	//return 1 if climate would kill tribe at this location
	// 6.49C/1000m 
	// -56.5 °C above 11000m

	//need to account for intelligence and strength to withstand
	float location_temp = Location_Temp(src_y, src_x);

	if(location_temp > (float)one->temp_h){ //if temp is higher than tribe can withstand
		//2 parts intel 1 part strength
		// 127 * 3 = 381
		//
		// initial tribes will have +/-4 added to their tolerance range
		// 
		if( ((float)one->temp_h + (float)floor( ((double)one->intelligence*2+one->strength) / 10) ) < location_temp ){ //if it's still higher
			return 1;
		}
	}
	if(location_temp < (float)one->temp_l){ //if temp is lower than tribe can withstand
		if( ((float)one->temp_l + (float)floor( ((double)one->intelligence*2+one->strength) / 10) ) > location_temp ){ //if it's still lower
			return 1;
		}
	}
	return 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% 
	uint32_t rand1, rand2;
	//uint32_t n1 = 0;
	int use_ceil = 0;
	float tmp;
	//double bigtmp;
	struct timeval cur;
	gettimeofday(&cur, NULL);
	uint64_t s = (unsigned int)cur.tv_usec + 3;
	rand1 = lrand(&s) % 2;
	if(rand1)
		use_ceil = 1;

	//Is_Alive(src_y, src_x)
	//three->alive = 1;
	//three->water_turns = 0;
	//three->water_direction = 0;
	//genetic
	tmp = (float)((float)one->intelligence + two->intelligence) / 2;
		three->intelligence = (unsigned char)( use_ceil ? ceil(tmp) : tmp );
	tmp = (float)((float)one->strength + two->strength) / 2;
		three->strength = (unsigned char)( use_ceil ? ceil(tmp) : tmp );
	tmp = (float)((float)one->speed + two->speed) / 2;
		three->speed = (unsigned char)( use_ceil ? ceil(tmp) : tmp );
	//keep within ranges
	tmp = (float)((float)one->temp_l + two->temp_l) / 2;
		three->temp_l = (unsigned char)( use_ceil ? ceil(tmp) : tmp );
	tmp = (float)((float)one->temp_h + two->temp_h) / 2;
		three->temp_h = (unsigned char)( use_ceil ? ceil(tmp) : tmp );
	tmp = (float)((float)one->max_age + two->max_age) / 2;
		three->max_age = (unsigned char)( use_ceil ? ceil(tmp) : tmp );

	//non-genetic
	tmp = (float)((float)one->social_factor + two->social_factor) / 2;
		three->social_factor = (unsigned char)( use_ceil ? ceil(tmp) : tmp );
	tmp = (float)((float)one->interspecies_violence + two->interspecies_violence) / 2;
		three->interspecies_violence = (unsigned char)( use_ceil ? ceil(tmp) : tmp );
	tmp = (float)((float)one->fight_flight_balance + two->fight_flight_balance) / 2;
		three->fight_flight_balance = (unsigned char)( use_ceil ? ceil(tmp) : tmp );
	tmp = (float)((float)one->migration_factor + two->migration_factor) / 2;
		three->migration_factor = (unsigned char)( use_ceil ? ceil(tmp) : 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;
	three->imunity = (unsigned char)IMUNITY;
	//suseconds_t signed integer type capable of storing values at least in the range [-1, 1000000].

	//rand1 = (int)ceil((double)1/( CHANCE_OF_EVOLUTION ));
	//rand1 = (int)ceil((double)1/( CHANCE_OF_EVOLUTION )*80/3*100);
	//if(lrand(&s) % 100 > rand1)
	//	return;

	//bigtmp = 1/CHANCE_OF_DEVIATION;

	//rand1 = (uint32_t)ceil(bigtmp*2147483648);
	//rand2 = (uint32_t)ceil(lrand(&s)/2);

	//rand2 = lrand(&s) % 2;
	rand1 = (int32_t)ceil(CHANCE_OF_EVOLUTION*3/8);
	rand2 = lrand(&s) % rand1;
	rand1 = lrand(&s) % rand1;
	if(rand2 != rand1)
		return;
	//for(n1=0; n1<CHANCE_OF_DEVIATION; n1++){
	//	rand1 = lrand(&s) % 2;
	//	rand2 = lrand(&s) % 2;
	//	if(rand2 == rand1)
	//		return;
	//}

	//3/80 total chance of new species after here !!!!!

	//1/2 chance we do a deviation
	unsigned char deviation = (unsigned char)(lrand(&s) % 2);
	//+1 deviation, otherwise -1
	//if(deviation)
	//	deviation = 1;
	//else
	//	deviation = 0;
	rand1 = lrand(&s) % 9; //which feild will be modified
	// 7/16 chance the selected feild is at an upper/lower limit
	// 7/32 chance deviation is the +1/-1 needed to create new species
	// 5/9 genetic deviation selected
	// ~ 1/1000 chance ultimately of new species (1/20 * 1/50)
	if(rand1 == 0){
		if(deviation){
			if(three->intelligence < 255){
				three->intelligence++;
				//printf("Smarter!\n");
			}
		}else{
			if(three->intelligence > 4)
				three->intelligence--;
		}
		return;
	}

	if(rand1 == 1){
		if(deviation){
			if(three->strength < 255)
				three->strength++;
		}else{
			if(three->strength > 4)
				three->strength--;
		}
		return;
	}
	if(rand1 == 2){
		if(deviation){
			if(three->speed < 255)
				three->speed++;
		}else{
			if(three->speed > 4)
				three->speed--;
		}
		return;
	}
	if(rand1 == 3){
		//stay within ranges
		if(deviation){
			if(three->temp_h < 39){
				three->temp_h++;
				three->temp_l++;
			}
		}else{
			if(three->temp_l > 4){
				three->temp_h--;
				three->temp_l--;
			}
		}
		return;
	}
	if(rand1 == 4){
		//stays within range 30 - 128yrs
		if(deviation){
			 if(three->max_age < 100)
				three->max_age++;
		}else{
			if(three->max_age > 26)
				three->max_age--;
		}
		return;
	}
	if(rand1 == 5){
		if(deviation){
			if(three->social_factor < 255)
				three->social_factor++;
		}else{
			if(three->social_factor > SOCIAL_FACTOR)
				three->social_factor--;
		}
		return;
	}
	if(rand1 == 6){
		if(deviation){
			if(three->interspecies_violence < 255)
				three->interspecies_violence++;
		}else{
			if(three->interspecies_violence > INTERSPECIES_VIOLENCE)
				three->interspecies_violence--;
		}
		return;
	}
	if(rand1 == 7){
		if(deviation){
			if(three->fight_flight_balance < 255)
				three->fight_flight_balance++;
		}else{
			if(three->fight_flight_balance > FIGHT_FLIGHT_BALANCE)
				three->fight_flight_balance--;
		}
		return;
	}
	//if(rand1 == 8){  //else
	if(deviation){
		if(three->migration_factor != 255)
			three->migration_factor++;
	}else{
		if(three->migration_factor > MIGRATION_FACTOR)
			three->migration_factor--;
	}
}

void Moves_Populate(uint32_t src_y, uint32_t src_x, struct Moves *moves){
	//populate struct moves with 4 surrounding coordinates
	const uint32_t width = WIDTH - 1;
	const uint32_t height = HEIGHT - 1;
	if(src_x != 0)
		moves[0].x = src_x - 1;
	else
		moves[0].x = width;
	moves[0].y = src_y;
	moves[0].valid  = 1;
	moves[0].rating = 4;

	if(src_x != width)
		moves[1].x = src_x + 1;
	else
		moves[1].x = 0;

	moves[1].y = src_y;
	moves[1].valid  = 1;
	moves[1].rating = 4;
	moves[2].x = src_x;

	if(src_y != 0)
		moves[2].y = src_y-1;
	else
		moves[2].y = height;

	moves[2].valid  = 1;
	moves[2].rating = 4;
	moves[3].x = src_x;

	if(src_y != height)
		moves[3].y = src_y+1;
	else
		moves[3].y = 0;

	moves[3].valid  = 1;
	moves[3].rating = 4;

}

int Tribe_Borders_Water(uint32_t src_y, uint32_t src_x){
	//return 1 if a tribe is bordering open water
	uint32_t n1 = 0;
	//uint32_t n2 = 0;
	struct Moves moves[4];
	Moves_Populate(src_y, src_x, moves);
	for(n1=0; n1<4; n1++){
		if(ia->dem[moves[n1].y][moves[n1].x] <= stats_t.cur_sealevel){
			//if(!life[moves[n1].y][moves[n1].x]->alive){
			if( !IS_SET(Alive, moves[n1].y, moves[n1].x) ){
				return 1;
			}
		}
	}

	return 0;
	//return n2==0 ? 0 : 1;
}

////////BREAKS THREADS !!!!!

int Tribe_Water_Migrate(uint32_t src_y, uint32_t src_x, uint32_t *dest){
	//migrate accross sea to land
	//return 0 moved to a valid land destination
	//return 1 died while water migrating
	//return 2 no available spots, did not migrate

	if(!Tribe_Borders_Water(src_y, src_x))
		return 2;

	uint32_t n1 = 0;
	uint32_t n2 = 0;
	struct timeval cur;
	uint32_t rand1;
	gettimeofday(&cur, NULL);
	uint64_t s = (uint64_t)cur.tv_usec + 3;
	struct Moves moves[4];
	//struct Moves moves2[4];
	char water_valid[4];
	Moves_Populate(src_y, src_x, moves);
	int ret_val = 1;
	//maximum 256
	uint32_t max_distance = ((uint32_t)life[src_y][src_x]->intelligence + life[src_y][src_x]->speed)/2;
	uint32_t distance = 0;
	uint32_t water_direction = 0;

	//first move must be to water
	for(n1=0; n1<4; n1++){
		if( !IS_SET(Alive, moves[n1].y, moves[n1].x) ){
			if(ia->dem[moves[n1].y][moves[n1].x] <= stats_t.cur_sealevel){
				moves[n1].valid = 1;
				n2++;
				continue;
			}
		}
		moves[n1].valid = 0;
	}
	//choose one random
	if(n2 != 0){
		rand1 = lrand(&s) % n2;
		n2 = 0;
		for(n1=0; n1<4; n1++){
			if(moves[n1].valid){
				if(n2 == rand1){
					//new location here
					dest[0] = moves[n1].y;
					dest[1] = moves[n1].x;
					//set direction?
					water_direction = n1;
				}
				n2++;
			}
		}
	}else{
		//return 2 no available spots, did not migrate
		return 2;
	}
	//plot course of migration
	for(distance=1; distance<max_distance; distance++){
		//return if found land
		if(ia->dem[dest[0]][dest[1]] > stats_t.cur_sealevel){
			ret_val = 0;
			break;
		}
		//populate potential moves
		Moves_Populate(dest[0], dest[1], moves);
		//find all valid moves (check land first)
		n2 = 0;
		for(n1=0; n1<4; n1++){
			if( !IS_SET(Alive, moves[n1].y, moves[n1].x) ){
				if(ia->dem[moves[n1].y][moves[n1].x] > stats_t.cur_sealevel){
					moves[n1].valid = 1;
					water_valid[n1] = 0;
					n2++;
				}else{
					moves[n1].valid = 0;
					water_valid[n1] = 1;
				}
				continue;
			}
			water_valid[n1] = 0;
			moves[n1].valid = 0;
		}
		//pick a move
		//if bordering open land, take it
		if(n2 != 0){
			rand1 = lrand(&s) % n2;
			n2 = 0;
			for(n1=0; n1<4; n1++){
				if(moves[n1].valid){
					if(n2 == rand1){
						dest[0] = moves[n1].y;
						dest[1] = moves[n1].x;
						ret_val = 0;
						break;

						//return 0;
					}
					n2++;
				}
			}
		}
		if(ret_val == 0)
			break;
		//if can see land, head toward it (can cause problems)
		/*
		for(n1=0; n1<4; n1++){
			Moves_Populate(moves[n1].y, moves[n1].x, moves2);
			for(n2=0; n2<4; n2++){
				if( !IS_SET(Alive, moves[n1].y, moves[n1].x) ){
					if(ia->dem[moves[n1].y][moves[n1].x] > stats_t.cur_sealevel){

					}
				}
			}
		}
		*/

		//maintain water direction if smart enough, else swim randomly
		rand1 = (uint32_t)ceil((double)life[src_y][src_x]->intelligence/256*100);
		if(lrand(&s) % 100 < rand1){
			if( !IS_SET(Alive, moves[water_direction].y, moves[water_direction].x) ){
				dest[0] = moves[water_direction].y;
				dest[1] = moves[water_direction].x;
				continue;
			}
		}
		//count valid water destinations
		n2 = 0;
		for(n1=0; n1<4; n1++){
			if(water_valid[n1])
				n2++;
		}
		if(n2 != 0){
			//pick one random
			rand1 = lrand(&s) % n2;
			n2 = 0;
			for(n1=0; n1<4; n1++){
				if(water_valid[n1]){
					if(n2 == rand1){
						dest[0] = moves[n1].y;
						dest[1] = moves[n1].x;
						water_direction = n1;
						break;
					}
					n2++;
				}
			}
		}
		//else{	
		//} cannot move
	}
	if(ret_val){
		KILL_Tribe(src_y, src_x);
		return 1;
	}
	//ret_val == 0){
	SET_ONE(Alive, dest[0], dest[1]);
	(void)memcpy((void *)life[dest[0]][dest[1]], (const void *)life[src_y][src_x], sizeof(struct Species));
	if(life[dest[0]][dest[1]]->imunity < 255)
		life[dest[0]][dest[1]]->imunity++;
	KILL_Tribe(src_y, src_x);
	return 0;
}

/*
	SET_ONE(Alive, dest[0], dest[1]);
	(void)memcpy((void *)life[dest[0]][dest[1]], (const void *)life[src_y][src_x], sizeof(struct Species));
	if(life[dest[0]][dest[1]]->imunity < 255)
		life[dest[0]][dest[1]]->imunity++;
	//set water_turns
	if(ret_val)
		life[dest[0]][dest[1]]->water_turns = 0;
	else
		life[dest[0]][dest[1]]->water_turns++;
    //clear old data
    KILL_Tribe(src_y, src_x);
	return ret_val;
}
*/

int Tribe_Migrate(uint32_t src_y, uint32_t src_x, uint32_t *dest){
	//return 1 if moved
	//put new location in dest

	uint32_t n1, n2;
	const uint32_t width = WIDTH - 1;
	const uint32_t height = HEIGHT - 1;
	struct Moves moves[4];
	//float temp_preferred = 0;
	//float temp_diff = 0;
	//float temp_actual = 0;

	//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_Populate(src_y, src_x, moves);

/*
	if(src_x != 0)
		moves[0].x = src_x - 1;
	else
		moves[0].x = width;

	moves[0].y = src_y;
	moves[0].valid  = 1;
	moves[0].rating = 4;

	if(src_x != width)
		moves[1].x = src_x + 1;
	else
		moves[1].x = 0;

	moves[1].y = src_y;
	moves[1].valid  = 1;
	moves[1].rating = 4;
	moves[2].x = src_x;

	if(src_y != 0)
		moves[2].y = src_y-1;
	else
		moves[2].y = height;

	moves[2].valid  = 1;
	moves[2].rating = 4;
	moves[3].x = src_x;

	if(src_y != height)
		moves[3].y = src_y+1;
	else
		moves[3].y = 0;

	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 = {0, 0};
	int cand_ties[4];

    struct timeval cur;
    uint32_t rand1;
    gettimeofday(&cur, NULL);
	uint64_t s = (uint64_t)cur.tv_usec + 3;

	for(n1=0; n1<4; n1++){
		//rule out moving to water
		if(stats_t.cur_sealevel >= ia->dem[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]->alive){
		if( IS_SET(Alive, moves[n1].y, moves[n1].x) ){
			moves[n1].valid = 0;
			continue;
		}
		//rule out moving to fatal climates
		if( Climate_Fatal(life[src_y][src_x], moves[n1].y, moves[n1].x) )
			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;
		//Moves_Populate(moves[n1].y, moves[n1].x, neighbors);
		//initialize neighbors for this potential move
		if(moves[n1].x != 0)
			neighbors[0].x = moves[n1].x-1;
		else
			neighbors[0].x = width;
		neighbors[0].y = moves[n1].y;
		if(moves[n1].x != width)
			neighbors[1].x = moves[n1].x+1;
		else
			neighbors[1].x = 0;
		neighbors[1].y = moves[n1].y;
		neighbors[2].x = moves[n1].x;
		if(moves[n1].y != 0)
			neighbors[2].y = moves[n1].y-1;
		else
			neighbors[2].y = height;
		neighbors[3].x = moves[n1].x;
		if(moves[n1].y != height)
			neighbors[3].y = moves[n1].y+1;
		else
			neighbors[3].y = 0;
		//calculate rating for this move threat/reward
			//if neighbor is empty terrain inc if climate is more favorable
			//ie: more toward the middle of temp_l - temp_h range than current position

			/*
			if(!life[moves[n1].y][moves[n1].x]->alive){
				temp_actual = Location_Temp(src_y, src_x);
				temp_diff = Location_Temp(moves[n1].y, moves[n1].x) - temp_actual;
				temp_preferred = (float)(life[src_y][src_x]->temp_l + life[src_y][src_x]->temp_h)/2;

				if(temp_diff < 0){ //am in a higher temp area
					//if lower temp is better than current location
					if( temp_preferred < temp_actual ){
						moves[n1].rating++;
						//continue;
					}
					//if(life[src_y][src_x]->temp_h
					//	moves[n1].rating++;
				}
				if(temp_diff > 0){ //am in a lower temp area
					//if higher temp is better
					if( temp_preferred > temp_actual ){
						moves[n1].rating++;
						//continue;
					}
				}
				//moves[n1].rating++;
				//continue;
			}
		*/
        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(!life[neighbors[n2].y][neighbors[n2].x]->alive){
			if( !IS_SET(Alive, neighbors[n2].y, neighbors[n2].x) ){
				moves[n1].rating++;
				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, or water
			moves[n1].rating++;

			//unless already on water ...
		}
	}
	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++;
		}
	}
	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
		rand1 = lrand(&s) %  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(stats_t.cur_sealevel < ia->dem[dest[0]][dest[1]]){
		//Move to destination
		SET_ONE(Alive, dest[0], dest[1]);
		//life[dest[0]][dest[1]]->alive = 1;
		(void)memcpy((void *)life[dest[0]][dest[1]], (const void *)life[src_y][src_x], sizeof(struct Species));
		if(life[dest[0]][dest[1]]->imunity < 255)
			life[dest[0]][dest[1]]->imunity++;
		//clear old data
		KILL_Tribe(src_y, src_x);
		return 1;
	}
	return 0;
}

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
	uint32_t rand1, rand2;
	//int32_t difference;
	struct timeval cur;
    gettimeofday(&cur, NULL);
    uint64_t s = (uint64_t)cur.tv_usec + 2;

	//if(!IS_SET( || !IS_SET()
	//	printf("Warning! Fight_Tribe called with non-alive tribe/s\n");

	//fight determined by  1 part strength, 1 part speed, 2 parts intelligence, and 1 part chance
	//rand1 = lrand(&s) % 10; //10% chance of random outcome, needs fixed !
	//if(rand1 == 5){
	//	return (int)(lrand(&s) % 2);
	//}
	//rand2 = lrand(&s) % 256;
	uint32_t rating1 = (uint32_t)one->intelligence*2 + one->strength;
	uint32_t rating2 = (uint32_t)two->intelligence*2 + two->strength;
	rating1 += one->speed;
	rating2 += two->speed;
	rating1 /= 16;
	rating2 /= 16;
	rand1 = lrand(&s) % (rating1+1);
	rand2 = lrand(&s) % (rating2+1);

	//difference = rating1 - rating2;
	//cur_age ?
	// 1 in 256 chance they are equal
	if(rand1 == rand2)
		return (int)(lrand(&s) % 2);
	if(rand1 > rand2)
		return 1;
	//if(rating2 > rating1)
		return 0;
	//if equal then random
	//return (int)(lrand(&s) % 2);
	//equal random
	//while(rating1 == rating2){
	//	rating1 = lrand(&s) % 10;
	//	rating2 = lrand(&s) % 10;
		//rating1 = (uint32_t)one->intelligence*2 + rand1 + one->strength;
		//rating2 = (uint32_t)two->intelligence*2 + rand2 + two->strength;
		//rating1 += one->speed;
		//rating2 += two->speed;
	//}
	//return rating1>rating2 ? 1 : 0;
}

void Tribe_Interactions(uint32_t src_y, uint32_t src_x, uint32_t tid){
	//evaluate all surrounding tribes for threat/reward take proper actions
	uint32_t n1, n2, n3;
	uint32_t rand1, rand2, rand3;
	int out_come;
	struct timeval cur;
	struct Neighbors{uint32_t y; uint32_t x; uint32_t occupied;}neighbors[4];
	struct Neighbors_T{uint32_t y; uint32_t x;}tmp[4];
	const uint32_t width = WIDTH - 1;
	const uint32_t height = HEIGHT - 1;
	//if(!life[src_y][src_x]->alive)
	//	printf("Warning Tribe_Interactions: Called for dead tribe!\n");
    gettimeofday(&cur, NULL);
    uint64_t s = (uint64_t)cur.tv_usec + 3;

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

	//for map wrap
	tmp[0].y = src_y;
	if(src_x != 0)
		tmp[0].x = src_x - 1;
	else
		tmp[0].x = width;

	tmp[1].y = src_y;
	if(src_x != width)
		tmp[1].x = src_x + 1;
	else
		tmp[1].x = 0;

	if(src_y != 0)
		tmp[2].y = src_y - 1;
	else
		tmp[2].y = height;
	tmp[2].x = src_x;

	if(src_y != height)
		tmp[3].y = src_y + 1;
	else
		tmp[3].y = 0;
	tmp[3].x = src_x;

	//mix them randomly
	rand1 = lrand(&s) % 4;  //pick of any
	rand2 = lrand(&s) % 3;  //pick of remaining 3
	rand3 = lrand(&s) % 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]->alive){
		if( IS_SET(Alive, neighbors[n1].y, neighbors[n1].x) ){
			//if(life[neighbors[n1].y][neighbors[n1].x]->water_turns == 0) //don't interact with water migraters
			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]) ){
				//check to see if we'll fight first !
				//if(!fought[src_y][src_x]){
				if( !IS_SET(Fought, src_y, src_x) ){
					rand1 = (uint32_t)ceil((double)life[src_y][src_x]->interspecies_violence/256*100);
					if(lrand(&s) % 100 < rand1){

					//rand1 = floor(INTERSPECIES_A_RANGE / life[src_y][src_x]->interspecies_violence);
					//rand2 = lrand(&s) % rand1;
					//if(lrand(&s) % rand1){
					//rand2 = lrand(&s) % INTERSPECIES_A_RANGE;  // 1/16 at 127
					//if(life[src_y][src_x]->interspecies_violence > rand2){//attacking
						//fought[src_y][src_x] = 1;
						//SET_ONE(Fought, src_y, src_x);
						out_come = Fight_Tribe( life[src_y][src_x], life[neighbors[n1].y][neighbors[n1].x] );
						if(out_come){//if the fight was won
							SET_ONE(Fought, src_y, src_x);
							KILL_Tribe(neighbors[n1].y, neighbors[n1].x);
							stats[tid].died_defending++;
							if(life[src_y][src_x]->imunity < 255)
								life[src_y][src_x]->imunity++;
							continue;
						}
						if(!out_come){ //died
							SET_ONE(Fought, neighbors[n1].y, neighbors[n1].x);
							KILL_Tribe(src_y, src_x);
							stats[tid].died_attacking++;
							if(life[neighbors[n1].y][neighbors[n1].x]->imunity < 255)
								life[neighbors[n1].y][neighbors[n1].x]->imunity++;
							return;
						}
					}
				}
				//if(mated[src_y][src_x])
				//	continue;
				//if(mated[neighbors[n1].y][neighbors[n1].x])
				//	continue;
				if(IS_SET(Mated, src_y, src_x))
					continue;
				if(IS_SET(Mated, neighbors[n1].y, neighbors[n1].x))
					continue;

				rand1 = (uint32_t)ceil((double)life[src_y][src_x]->social_factor/256*100);
				if(lrand(&s) % 100 < rand1){
				//rand2 = lrand(&s) % life[src_y][src_x]->social_factor + 1; // 1/2 at 127
				//rand1 = lrand(&s) % INTERSPECIES_M_RANGE + 1;  //high chance
				//if(rand2 > rand1){
				//if(life[src_y][src_x]->social_factor > rand1){ //are mating
					out_come = 0;
					//choose open space for offspring
					for(n2=0; n2<4; n2++){
						if(neighbors[n2].occupied == 0){
							if(stats_t.cur_sealevel < ia->dem[neighbors[n2].y][neighbors[n2].x] ){
								out_come = 1;
								break;
							}
						}
					}
					//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;
						//mated[neighbors[n2].y][neighbors[n2].x] = 1; //to keep it from mating/fighting during it's first year of life
						SET_ONE(Mated, src_y, src_x);
						SET_ONE(Mated, neighbors[n1].y, neighbors[n1].x);
						SET_ONE(Mated, neighbors[n2].y, neighbors[n2].x);
						//fought[neighbors[n2].y][neighbors[n2].x] = 1; //
						SET_ONE(Fought, neighbors[n2].y, neighbors[n2].x);
						//life[neighbors[n2].y][neighbors[n2].x]->alive = 1;
						SET_ONE(Alive, neighbors[n2].y, neighbors[n2].x);

						Create_Life(life[src_y][src_x], life[neighbors[n1].y][neighbors[n1].x], life[neighbors[n2].y][neighbors[n2].x]);
						stats[tid].new_life++;
						life_speed_up_Y[neighbors[n2].y] = 1;
						life_speed_up_X[neighbors[n2].x] = 1;
						if( !Is_Same_Species(life[src_y][src_x], life[neighbors[n2].y][neighbors[n2].x]) )
							stats[tid].new_species++;
						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
				if( !IS_SET(Fought, src_y, src_x) ){
					rand1 = (uint32_t)ceil((double)life[src_y][src_x]->fight_flight_balance/256*100);
					if(lrand(&s) % 100 < rand1){
					//rand2 = lrand(&s) % ENEMY_A_RANGE;
					//if(life[src_y][src_x]->fight_flight_balance > rand2){//attacking
						//fought[src_y][src_x] = 1;
						//SET_TOGGLE(Fought, src_y, src_x);
						out_come = Fight_Tribe( life[src_y][src_x], life[neighbors[n1].y][neighbors[n1].x] );
						if(out_come){//fight was won
							SET_ONE(Fought, src_y, src_x);
							KILL_Tribe(neighbors[n1].y, neighbors[n1].x);
							stats[tid].died_defending++;
							if(life[src_y][src_x]->imunity < 255)
								life[src_y][src_x]->imunity++;
						}
						if(!out_come){ //died
							SET_ONE(Fought, neighbors[n1].y, neighbors[n1].x);
							KILL_Tribe(src_y, src_x);
							stats[tid].died_attacking++;
							if(life[neighbors[n1].y][neighbors[n1].x]->imunity < 255)
								life[neighbors[n1].y][neighbors[n1].x]->imunity++;
							return;
						}
					}
				}
			}
		}
		//if(fought[src_y][src_x]){
		//	if(mated[src_y][src_x]){
		//		return;
		//	}
		//}
		if( IS_SET(Fought, src_y, src_x) ){
			if( IS_SET(Mated, src_y, src_x) ){
				return;
			}
		}
	}
}

/*
void FM_Alloc(void){
	uint32_t 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);
}
*/

void FM_Reset(uint32_t start, uint32_t end){
	uint32_t h;
	for(h=start; h<end; h++){
		(void)memset( (void *)Fought[h], '\0', sizeof(unsigned char)*(size_t)ceil(WIDTH/8));
		(void)memset( (void *)Mated[h], '\0', sizeof(unsigned char)*(size_t)ceil(WIDTH/8));
	}
}

void Life_Speed_Reset(void){
	uint32_t h;
	uint32_t w;
	(void)memset( (void *)life_speed_up_X, '\0', sizeof(unsigned char)*(size_t)WIDTH);
	(void)memset( (void *)life_speed_up_Y, '\0', sizeof(unsigned char)*(size_t)HEIGHT);
	for(h=0; h<HEIGHT; h++){
		for(w=0; w<WIDTH; w++){
			if( IS_SET(Alive, h, w) ){
				life_speed_up_X[w] = 1;
				life_speed_up_Y[h] = 1;
			}
		}
	}
}
void *Tribe_Actions(void *tid){
	//master thread
	//initiate actions migrate/combat/desease/create_life/migrate/socialize
	uint32_t t = *(unsigned int *)tid;
	uint32_t y = 0;
	uint32_t x = 0;
	uint32_t x_s = 0;
	//uint32_t x_h = 0;
	int right_to_left = 0;
	//int dec = 0;
	int stop = 0;
	int first_member = 0;
	uint32_t dest[] = {0, 0}; //y x
	char did_move = 0;
	//struct timeval starttime,endtime;
	struct timeval cur;
    uint32_t rand1 = 0;
	uint32_t rand2 = 0;
	//int cur_sealevel = ia->cur_sealevel;
    gettimeofday(&cur, NULL);
	//printf("%u\n", Thread_Step);
    uint64_t s = (uint64_t)cur.tv_usec + 3;
	//char *life_speed_up_H = (char *)malloc(Thread_Step);
	//char life_speed_up_W[WIDTH]; //= (char *)malloc(WIDTH);
	//int row_half = 0;
	//int row_ceiling = 0;
	uint32_t region_offset = 0;
	uint32_t region = 0;
	//double year_runtime = 0;

	//do first half of rows

	//sychronize threads

	//second half

	//sychronize threads

	//stats / image handled

	//reset arrays as necesary

	//check for exit signals and clean up

	//(void)memset( (void *)life_speed_up_H, '\0', sizeof(char)*HEIGHT );
	//(void)memset( (void *)&life_speed_up_W, '\0', sizeof(char)*WIDTH );
	//printf("%u Here !\n", t);
	//sleep(5);
	if(t == 0)
		gettimeofday(&Year_Starttime, NULL);

	while(No_Exit == 1){
		//(void)memset( (void *)life_speed_up_H, '\0', sizeof(char)*HEIGHT );
		//(void)memset( (void *)life_speed_up_W, '\0', sizeof(char)*WIDTH );
		for(region_offset=0; region_offset<5; region_offset++){

			//printf("t: %u reg_off: %u\n", t, region_offset);
			for(y = region_offset; y<HEIGHT-5; y+=5){
				region = (uint32_t)y/5;
				//for(region=Actions_t_info[t].start_h; region<360; region++){

				//if(Region_Handled[region])
				//	continue;
				if( pthread_mutex_trylock( &Region_Mutexes[region] ) != 0)
					continue;
				//pthread_mutex_lock( &Region_Mutexes[region] );
				//Region_Handled[region] = 1;
				//pthread_mutex_unlock( &Region_Mutexes[region] );


				//if(Region_Handled[region]){
				//	pthread_mutex_unlock( &Region_Mutexes[region] );
				//	continue;
				//}
				//Region_Handled[region] = 1;
				//pthread_mutex_unlock( &Region_Mutexes[region] );
				

				//for(y_offset = region*5+region_offset; y_offset<region*5+5; y_offset++){
				//y=region*5+region_offset;

				if(!life_speed_up_Y[y])
					continue;
					//randomly choose to start from right or left of row
					rand1 = lrand(&s) % 2;
					//rand2 = lrand(&s) % 511;
				if( rand1 ){
					right_to_left = 0;
					x_s = WIDTH - 1;
					x = 0;
				}else{
					right_to_left = 1;
					x_s = 0;
					x = WIDTH - 1;
				}
				stop = 0;
				first_member = 1;
				while(!stop){
					//if(stop)
					//	break;
					if(right_to_left){
						if(!first_member)
							x--;
						else
							first_member = 0;
					}else{
						if(!first_member)
							x++;
						else
							first_member = 0;
					}
					if(x == x_s)
						stop = 1;
					if(!life_speed_up_X[x])
						continue;
					//if(life[y][x]->alive){ //if there is life at this location
//printf("here 1\n");
					if( IS_SET(Alive, y, x) ){
//printf("here 2\n");
						//get one year older
						life[y][x]->cur_age++;
						//die from old age?  // 1/36 chance for initial tribes
						if(life[y][x]->cur_age == life[y][x]->max_age ){
							KILL_Tribe(y, x);
							stats[t].old_age++;
							continue;
						}
//printf("here 3\n");
						rand1 = (uint32_t)ceil((double)life[y][x]->imunity/256*100);
						rand2 = lrand(&s) % 100;
						if(rand2 > rand1){
						//rand2 = lrand(&s) % IMUNITY_RANGE; // 1/16 at 127   1/32 at 255
						//if(life[y][x]->imunity > rand2){
							//printf("year: %u rand1: %d rand2: %d\n", stats_t.year, rand1, rand2);
							KILL_Tribe(y, x);
							stats[t].disease++;
							continue;
						}

    //return 0 moved to a valid land destination
    //return 1 died while water migrating
    //return 2 no available spots, did not migrate

						//see if tribe will attempt water migration
						rand1 = (uint32_t)ceil((double)WATER_MIGRATION_RANGE/256*100);
						if(lrand(&s) % 100 < rand1){

////// BREAKS THREADS !!!
							did_move = Tribe_Water_Migrate(y, x, dest);

							if(did_move){ //return 1 died while water migrating
								KILL_Tribe(y, x);
								stats[t].drown++;
								continue;
							}
							if(did_move == 0){ //return 0 moved to a valid land destination
								did_move = 1;
							}else{
								//if(did_move == 2){ //return 2 no available spots, did not migrate
								did_move = 0;
							}
						}else{ //if tribe is not water migrating
							rand1 = (uint32_t)ceil((double)life[y][x]->migration_factor/256*100);
							//rand2 = lrand(&s) % MIGRATION_RANGE;  // 1/4 at 127 
							//if(life[y][x]->migration_factor > rand2){  //tribe will attempt to migrate
							if(lrand(&s) % 100 < rand1){
								did_move = Tribe_Migrate(y, x, dest);

								if(did_move == 0){ //couldn't find a spot, try to water migrate
									rand1 = (uint32_t)ceil((double)WATER_MIGRATION_RANGE/256*100);
									if(lrand(&s) % 100 < rand1){
										did_move = Tribe_Water_Migrate(y, x, dest);
										if(did_move){ //return 1 died while water migrating
											KILL_Tribe(y, x);
											stats[t].drown++;
											continue;
										}
										if(did_move == 0){
											did_move = 1;
										}else{
											did_move = 0;
										}
									}
								}

							}
							//this tribe won't/can't migrate regardless
							if(stats_t.cur_sealevel >= ia->dem[y][x]){ //drown
								KILL_Tribe(y, x);
								stats[t].drown++;
								continue;
							}

							if(did_move){
								if( Climate_Fatal(life[dest[0]][dest[1]], dest[0], dest[1]) ){
									KILL_Tribe(dest[0], dest[1]);
									stats[t].exposure++;
									continue;
								}
								Tribe_Interactions(dest[0], dest[1], t);
							}else{
								if( Climate_Fatal(life[y][x], y, x) ){
									KILL_Tribe(y, x);
									stats[t].exposure++;
									continue;
								}
								Tribe_Interactions(y, x, t);
							}
							continue;
						}

					}//end of if life != NULL
				}//end of X loop
				//pthread_mutex_unlock( &Region_Mutexes[region] );
			}//end of Y loop

			//(void)memset((void *)Region_Handled, '\0', HEIGHT/5*sizeof(unsigned char));

			pthread_barrier_wait(&Barrier1);  //region offset change 0-4
			//pthread_mutex_lock( &Mutex2 );
			//if(!Handled_Reset){
			//	Handled_Reset = 1;
			//	pthread_mutex_unlock( &Mutex2 );
			//}
			if(t == 0){
				for(y=0; y<((uint32_t)HEIGHT/5); y++){
					if( pthread_mutex_unlock( &Region_Mutexes[y] ) != 0){
						Stats_Handled = 1;
						No_Exit = 2;
						//bla !!
						pthread_exit(NULL);
					}
				}
			}
			//	(void)memset((void *)Region_Handled, '\0', (size_t)HEIGHT/5*sizeof(unsigned char));
			//}
			//pthread_barrier_wait(&Barrier2);
			pthread_barrier_wait(&Barrier2);
			//start next region_offset
		}//end of year
		//pthread_barrier_wait(&Barrier2);

		//FM_Reset(Actions_t_info[t].start_h, Actions_t_info[t].end_h);
		//printf("here 1\n");
		//first thread to reach it
		pthread_mutex_lock( &Mutex1 );
		if(!Stats_Handled){
			Stats_Handled = 1;
			//pthread_mutex_unlock( &Mutex1 );
			stats_t.year++;
			FM_Reset(0, HEIGHT); //can thread
			//Life_Speed_Reset();  //can thread
			gettimeofday(&Year_Endtime, NULL);
			Year_Runtime += ((double)(Year_Endtime.tv_sec*1000000-Year_Starttime.tv_sec*1000000+Year_Endtime.tv_usec-Year_Starttime.tv_usec))/1000000;
			gettimeofday(&Year_Starttime, NULL);
			if(stats_t.year % CLIMATE_YEARS == 0){
				Adjust_Sea_Level(0);
				Adjust_Climate(0);
				if(stats_t.sea_rising)
					Life_Speed_Reset();  //can thread
			}
			if(stats_t.year % Backup_Freq == 0){
				Backup_Freq_Runtime += Year_Runtime;
				Gen_Detailed_Counts();
				pthread_mutex_unlock( &Mutex3 );
				No_Exit = !Save_Current_State();  //cause an exit if failed
				pthread_mutex_unlock( &Mutex3 );
			}else if(No_Exit == 0){  //save and exit
				Backup_Freq_Runtime += Year_Runtime;
				Gen_Detailed_Counts();
				(void)Save_Current_State();  //will still exit gracefully
			}
			//gettimeofday(&Year_Starttime, NULL);
		}
		pthread_mutex_unlock( &Mutex1 );

		pthread_barrier_wait(&Barrier3); //barrier for full year

		pthread_mutex_lock( &Mutex2 );
		Stats_Handled = 0;
		pthread_mutex_unlock( &Mutex2 );
		//printf("here 2\n");

	}//main thread loop

	pthread_exit(NULL);
}



void Drawl_Image(void){
	uint32_t n1, n2;
	unsigned char rgb[3];
	for(n1=0; n1<HEIGHT; n1++){
		for(n2=0; n2<WIDTH; n2++){
			//if(ia->dem[n1][n2] > stats_t.cur_sealevel){
			//if(!life[n1][n2]->alive){
			if( !IS_SET(Alive, n1, n2) ){
				if(ia->dem[n1][n2] > stats_t.cur_sealevel){
					rgb[0] = 0;
					rgb[1] = 255;
					rgb[2] = 0;
				}else{
					rgb[0] = 0;
					rgb[1] = 0;
					rgb[2] = 255;
				}
			}else{
				Gen_Tribe_Color(life[n1][n2], rgb);
			}
			//}else{
			//	rgb[0] = 0;
			//	rgb[1] = 0;
			//	rgb[2] = 255;
			//}
			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];
		}
	}
}