#include "Dice_Funcs.h"

static uint8_t Has_Straight(uint8_t *roll_results, uint8_t dice);
static uint8_t Has_Three_Pair(uint8_t *num_counts, uint8_t dice);
static void Gen_Num_Counts(uint8_t *Dv, uint8_t *Nc, uint8_t Dice);
static uint32_t Gen_Num_Scores(uint32_t *Num_Scores, uint8_t *Num_Counts);
static uint8_t Gen_Kept_Dice(uint8_t *Dv, uint8_t *Kd);
static uint32_t Select_Best(uint8_t *counts, uint32_t *scores, uint8_t dice_rolled);
static uint8_t Has_Zilch(uint8_t *counts, uint8_t *roll_results, uint8_t dice_rolled);

void Player_End_Turn(void){
	uint8_t num1 = 0;
	gs.rdc = gs.Dice;
	pd[gs.Cur_Player].onboard = 0;
	pd[gs.Cur_Player].cumulative_score += pd[gs.Cur_Player].turn_score;
	pd[gs.Cur_Player].turn_score = 0;
	//if(gs.Cur_Player < (gs.Num_Players-1))
	//	gs.Cur_Player++;
	//else
	//	gs.Cur_Player = 0;
	gs.Roll_Count = 0;
	//(void)memset(gs.Num_Scores, '\0', SIDES);
	(void)memset(gs.Dice_Selected, '\0', gs.Dice);
	Blank_Dice();
	//for(num1=0; num1<gs.Dice; num1++){
	//	Dice_Selections[num1] = 0;
		//Dice_Values[num1] = 
	//}
}

void Next_Player(void){
	//uint8_t num1 = 0;
	if(gs.Cur_Player < (gs.Num_Players-1))
		gs.Cur_Player++;
	else
		gs.Cur_Player = 0;
}

uint8_t Has_Zilch(uint8_t *counts, uint8_t *roll_results, uint8_t dice_rolled){
	//return FALSE if have 1's 5's, 3 of kind, straights, or 3 pairs
	uint8_t num1 = 0;
	//uint8_t num2 = gs.rdc;
	for(num1=0; num1<dice_rolled; num1++){
		if(gs.Dice_Values[num1] == 1)
			return FALSE;
		if(gs.Dice_Values[num1] == 5)
			return FALSE;
	}
	for(num1=0; num1<SIDES; num1++){
		if(counts[num1] > 2)
			return FALSE;
	}
	if(Has_Straight(roll_results, dice_rolled))
		return FALSE;
	if(Has_Three_Pair(counts, dice_rolled))
		return FALSE;
	return TRUE;
}

void Reset_Dice_Selection(void){
	uint8_t num1 = 0;
	uint8_t num2 = gs.Dice;
	for(num1=0; num1<num2; num1++){
		gs.Dice_Selected[num1] = 0;
	}
}

void Blank_Dice(void){
	uint8_t num1 = 0;
	for(num1=0; num1<gs.Dice; num1++){
		gs.Dice_Blank[num1] = 1;
	}
}

uint8_t Player_Can_Roll(void){
	//return TRUE or FALSE
	//uint8_t num1 =
	//uint8_t num2 =
	//pd[gs.Cur_Player].rdc
	if(gs.Roll_Count == 0){
		return TRUE;
	}
	//if player has zilch return FALSE

	if(pd[gs.Cur_Player].type == COMPUTER_PLAYER){
		//do checks for things that would cause TRUE
		if(pd[gs.Cur_Player].onboard != 1){
        	if(pd[gs.Cur_Player].turn_score < gs.Min_Get_Onboard){
				return TRUE;
			}
			//get onboard and return FALSE
			return FALSE;
		}
		if(pd[gs.Cur_Player].turn_score < pd[gs.Cur_Player].min_score_will_keep){
			return TRUE;
		}
		if(gs.rdc > pd[gs.Cur_Player].min_dice_will_roll){
			return TRUE;
		}
		return FALSE;
	}
	//if(pd[gs.Cur_Player].type == LOCAL_PLAYER){

	if(Valid_Dice_Selection()){
		return TRUE;
	}else{
		uint8_t *Nc = (uint8_t *)malloc(sizeof(uint8_t)*gs.rdc);
		Gen_Num_Counts(gs.Dice_Values, Nc, gs.rdc);
		if( Has_Zilch(Nc, gs.Dice_Values, gs.rdc) == TRUE){
			pd[gs.Cur_Player].turn_score = 0;
			free(Nc);
			return FALSE;
		}
		//another chance to redo dice selection here.
		free(Nc);
		return INVALID_DICE_SELECTION;
	}
	//return Valid_Dice_Selection();

	//}
	return FALSE;
}


/*
static uint8_t Has_Straight(uint8_t *roll_results, uint8_t dice){
	// return 1 if dice are a straight, else 0 
	//should only be run when dice == full amount (first roll)
	if(dice == 1)
		return 1;
	if(dice == 0)
	return 0;
*/

//static uint8_t Has_Straight(uint8_t dice){

//static void Mark_Straight(void){
	

//}

//static void Mark_Three_Pair(void){
//}





static uint8_t Has_Straight(uint8_t *roll_results, uint8_t dice){
	if(dice != gs.Dice)
		return FALSE;
	uint8_t num1 = 0;
	uint8_t num2 = SIDES;
	uint8_t match_found = 0;
	uint8_t *roll_results_ordered = (uint8_t *)malloc(dice*sizeof(uint8_t) );

	//find lowest rolled number
	for(num1=0; num1<dice; num1++){
		if(roll_results[num1] < num2)
			num2 = roll_results[num1];
	}
	roll_results_ordered[0] = num2;

	//search for roll that is 1 higher than previous for dice, return 0 if broken
	for(num1=1; num1<dice; num1++){
		match_found = 0;
		for(num2=0; num2<dice; num2++){
			if(roll_results[num2] == roll_results_ordered[num1-1]+1){
				roll_results_ordered[num1] = roll_results[num2];
				match_found = 1;
				break;
			}
		}
		if(match_found == 0)
			return FALSE;
	}
	free(roll_results_ordered);
	return TRUE;
}

/*
static uint8_t Has_Three_Pair(uint8_t *num_counts, uint8_t dice){
	// return 1 if has 3 pair else 0
	if(dice < 6)
		return 0;
*/
//static uint8_t Has_Three_Pair(void){
static uint8_t Has_Three_Pair(uint8_t *num_counts, uint8_t dice){
	if(dice < 6)
		return FALSE;
	uint8_t num1 = 0;
	uint8_t num2 = 0;
	for(num1=0; num1<SIDES; num1++){
		if(num_counts[num1] > 1)
			num2++;
	}
	if(num2 > 2)
		return TRUE;
	return FALSE;
}

void Adjust_RDC(void){
	uint8_t num1 = 0;
	//uint8_t num2 = gs.rdc;
	uint8_t selected = 0;
	//count number selected
	for(num1=0; num1<gs.rdc; num1++){
		if(gs.Dice_Selected[num1] == 1)
			selected++;
	}
	//new rdc is old rdc - selected
	if(selected < gs.rdc)
		gs.rdc -= selected;
	else
		gs.rdc = gs.Dice;
	//set blanked dice
	//for(num1=0; num1<gs.Dice; num1++){
	//	if(num1

	//}
}

void Roll_Dice(void){
	uint8_t num1 = 0;
	uint8_t num2 = gs.rdc;
	if(gs.Roll_Count != 0){
		pd[gs.Cur_Player].turn_score += Score_Of_Selected();
		//pd[gs.Cur_Player].cumulative_score += Score_Of_Selected();
	}
	gs.Roll_Count++;
	for(num1=0; num1<gs.Dice; num1++){
		if(num1<num2){
			gs.Dice_Blank[num1] = 0;
			gs.Dice_Values[num1] = (uint8_t)( lrand(&(gs.rseed)) % SIDES + 1);
		}else{
			gs.Dice_Blank[num1] = 1;
		}
	}
}

static void Gen_Num_Counts(uint8_t *Dv, uint8_t *Nc, uint8_t Dice){
	uint8_t num1 = 0;
	//uint8_t num2 = pd[gs.Cur_Player].rdc;
	(void)memset(Nc, '\0', sizeof(uint8_t) * SIDES);
	for(num1=0; num1<Dice; num1++){
		Nc[ Dv[num1]-1 ]++;
	}
}

static uint32_t Gen_Num_Scores(uint32_t *Num_Scores, uint8_t *Num_Counts){
	uint8_t num1 = 0;
	uint8_t num2 = 0;
	uint32_t Score = 0;
	(void)memset(Num_Scores, '\0', sizeof(uint32_t) * SIDES);
	for(num1=0; num1<SIDES; num1++){
		if(num1 == 0){
			if(Num_Counts[0] < 3){
				Num_Scores[0] = 100*Num_Counts[0];
				continue;
			}
			Num_Scores[0] = 1000;
			for(num2=3; num2<Num_Counts[0]; num2++){
				Num_Scores[0] *= 2;
			}
			continue;
		}
		if(num1 == 4){
			if(Num_Counts[4] < 3){
				Num_Scores[4] = 50*Num_Counts[4];
				continue;
			}
			Num_Scores[4] = 500;
			for(num2=3; num2<Num_Counts[4]; num2++){
				Num_Scores[4] *= 2;
			}
			continue;
		}
		if(Num_Counts[num1] < 3)
			continue;
		Num_Scores[num1] = 100*(num1+1);
		for(num2=3; num2<Num_Counts[num1]; num2++){
			Num_Scores[num1] *= 2;
		}
	}
	//Score = 0;
	for(num1=0; num1<SIDES; num1++){
		Score += Num_Scores[num1];
	}
	return Score;
}

static uint8_t Gen_Kept_Dice(uint8_t *Dv, uint8_t *Kd){
	//marks 1's and 5's
	uint8_t num1 = 0;
	uint8_t num2 = gs.rdc;
	uint8_t Dice_Kept = 0;

	(void)memset(Kd, '\0', sizeof(uint8_t) * num2);
	for(num1=0; num1<num2; num1++){
		if(Dv[num1] == 1){
			Kd[num1] = 1;
			Dice_Kept++;
			continue;
		}
		if(Dv[num1] == 5){
			Kd[num1] = 1;
			Dice_Kept++;
		}
	}
	return Dice_Kept;
}

uint32_t Score_Of_Selected(void){
	uint8_t *dice;
	uint8_t counts[SIDES];
	uint32_t scores[SIDES];
	//uint32_t
	uint8_t dice_selected = 0;
	uint8_t num1 = 0;
	uint32_t Score = 0;

	//place selected dice values into local array
	for(num1=0; num1<gs.rdc; num1++){
		if(gs.Dice_Selected[num1] == 1)
			dice_selected++;
	}
	dice = (uint8_t *)malloc(sizeof(uint8_t)*dice_selected);
	dice_selected = 0;
	for(num1=0; num1<gs.rdc; num1++){
		if(gs.Dice_Selected[num1] == 1){
			dice[dice_selected] = gs.Dice_Values[num1];
			dice_selected++;
		}
	}
	//dice_selected = num2;
	//num counts
	Gen_Num_Counts(dice, counts, dice_selected);
	//scores
	Score = Gen_Num_Scores(scores, counts);
	//straight gs.Straight_Score
	if(Has_Straight(dice, dice_selected)){
		if(gs.Straight_Score > Score)
			Score = gs.Straight_Score;
	}
	free(dice);
	//3 pair gs.Three_Pair_Score
	if(Has_Three_Pair(counts, dice_selected)){
		if(gs.Three_Pairs_Score > Score)
			Score = gs.Three_Pairs_Score;
	}
	return Score;
}

/*
static uint32_t Roll_Dice_old(uint32_t p_num){
//static uint32_t Roll_Dice(uint64_t *s, struct Player_Data *pd){
	uint32_t num1, num2, num3;

	//uint8_t roll_results[Dice];
	uint8_t *roll_results = (uint8_t *)malloc(gs.Dice * sizeof(uint8_t));

	uint8_t num_counts[SIDES];
	uint32_t num_scores[SIDES];

	//uint8_t kept_dice[DICE];
	uint8_t *kept_dice = (uint8_t *)malloc(gs.Dice * sizeof(uint8_t));

	uint32_t score = 0;
	uint32_t score_final = 0;
	uint32_t rolling_dice = gs.Dice;
	uint8_t turn_not_over = 1;

	while(turn_not_over == 1){
		printf("\t");
		for(num2=0; num2<rolling_dice; num2++){
			roll_results[num2] = lrand(&(pd[p_num].rseed)) % SIDES + 1;
			printf("%u ", roll_results[num2]);
		}
		printf("\n");
		sleep(1);
		(void)memset(num_counts, '\0', sizeof(uint8_t) * SIDES);
        for(num2=0; num2<rolling_dice; num2++){
            num_counts[ roll_results[num2]-1 ]++;
        }
		(void)memset(num_scores, '\0', sizeof(uint32_t) * SIDES);
		(void)memset(kept_dice, '\0', sizeof(uint8_t) * gs.Dice);
		//set kept_dice
		for(num2=0; num2<rolling_dice; num2++){
			if(roll_results[num2] == 1 || roll_results[num2] == 5){
				kept_dice[num2] = 1;
			}
		}
		for(num2=0; num2<SIDES; num2++){
			if(num_counts[num2] > 2){
				for(num3=0; num3<rolling_dice; num3++){
					if(roll_results[num3] == num2+1)
						kept_dice[num3] = 1;
				}
			}
		}
		//set num_scores
		for(num2=0; num2<SIDES; num2++){
			if(num2 == 0){
				if(num_counts[0] < 3){
					num_scores[0] = 100*num_counts[0];
					continue;
				}
				num_scores[0] = 1000;
				for(num3=3; num3<num_counts[0]; num3++){
					num_scores[0] *= 2;
				}
				continue;
			}
			if(num2 == 4){
				if(num_counts[4] < 3){
					num_scores[4] = 50*num_counts[4];
					continue;
				}
				num_scores[4] = 500;
				for(num3=3; num3<num_counts[4]; num3++){
					num_scores[4] *= 2;
				}
				continue;
			}
			if(num_counts[num2] < 3)
				continue;
			num_scores[num2] = 100*(num2+1);
			for(num3=3; num3<num_counts[num2]; num3++){
				num_scores[num2] *= 2;
			}
		}
		score = 0;
		for(num3=0; num3<SIDES; num3++){
			score += num_scores[num3];
		}
		if(rolling_dice > 5){
			if( Has_Three_Pair(num_counts, rolling_dice) ){
			//must do entirely different if greater than 6 dice
			//could potentially have multiple three pairs ...
			//or three pairs + 1 + 5 + 3 of kind + etc.
				if(score < gs.Three_Pairs_Score){
					rolling_dice = gs.Dice;
					score_final += gs.Three_Pairs_Score;
					continue;
				}
			}
		}
		if(rolling_dice == gs.Dice){
			if( Has_Straight(roll_results, rolling_dice) ){
				if(score < gs.Straight_Score){
					rolling_dice = gs.Dice;
					score_final += gs.Straight_Score;
					continue;
				}
			}
		}
		//do zilch test here
		if(score == 0){
			turn_not_over = 0;
			score_final = 0;
			continue;
		}

*/

/*
uint32_t AI_Select_Dice(void){
	//mark the dice that the AI will keep, then return the score of those
	//set end turn if needed
    uint8_t *dice;
    uint8_t counts[SIDES];
    uint32_t scores[SIDES];
    //uint32_t
    uint8_t dice_selected = 0;
    uint8_t num1 = 0;
    uint8_t Score = 0;

    //place selected dice values into local array
    for(num1=0; num1<pd[gs.Cur_Player].rdc; num1++){
        if(gs.Dice_Selected[num1] == 1)
            dice_selected++;
    }
    dice = (uint8_t *)malloc(sizeof(uint8_t)*dice_selected);
    dice_selected = 0;
    for(num1=0; num1<pd[gs.Cur_Player].rdc; num1++){
        if(gs.Dice_Selected[num1] == 1){
            dice[dice_selected] = gs.Dice[num1];
            dice_selected++;
        }
    }
	if(dice_selected == pd[gs.Cur_Player].rdc){ 
		for(num1=0; num1<dice_selected; num1++){
			Dice_Selections[num1] = 1;
		}

	}
   //dice_selected = num2;
    //num counts
    Gen_Num_Counts(dice, counts, dice_selected);
    //scores
    Score = Gen_Num_Scores(scores, counts);
    //straight gs.Straight_Score
    if(Has_Straight(dice, dice_selected)){
        if(gs.Straight_Score > Score)
            Score = gs.Straight_Score;
    }
    free(dice);
    //3 pair gs.Three_Pair_Score
    if(Has_Three_Pair(counts, dice_selected)){
        if(gs.Three_Pair_Score > Score)
            Score = gs.Three_Pair_Score;
    }
    return Score;
}
*/






uint32_t AI_Select_Dice(void){
	uint8_t dice_rolled = gs.rdc;
	uint8_t *dice_tmp = (uint8_t *)malloc(sizeof(uint8_t)*dice_rolled);
    uint8_t counts[SIDES];
    uint32_t scores[SIDES];
	uint8_t num1 = 0;
	uint8_t	num2 = 0;
	uint8_t dice_left = 0;
	uint32_t Score = 0;

	//(void)memset(gs.Dice_Selections, '\0', gs.Dice);
	Reset_Dice_Selection();
	//mark 1's and 5's
	num2 = Gen_Kept_Dice(gs.Dice_Values, dice_tmp);
	if( num2 == dice_rolled){
		for(num1=0; num1<dice_rolled; num1++){
			gs.Dice_Selected[num1] = 1;
			//if(gs.Dice_Values[num1] == 1)
			//	Score += 
			//else if(gs.Dice_Values[num1] == 5)
			//	Score += 
		}
		free(dice_tmp);
		//rdc set to max
		gs.rdc = gs.Dice;
		//Score = 
		return Score_Of_Selected();
	}
	//else{
	//	dice_left = dice_rolled - num2;
	//}
	free(dice_tmp);
    //num counts
	Gen_Num_Counts(gs.Dice_Values, counts, dice_rolled);
    //scores
	Score = Gen_Num_Scores(scores, counts);
	if(Has_Straight(gs.Dice_Values, dice_rolled)){
		if(Score < gs.Straight_Score){
			//mark straight
			for(num2=0; num2<dice_rolled; num2++){
				gs.Dice_Selected[num2] = 1;
			}
			gs.rdc = gs.Dice;
			return gs.Straight_Score;
		}
	}
	if(Has_Three_Pair(counts, dice_rolled)){
		if(Score < gs.Three_Pairs_Score){
			//mark 3 pair
			for(num1=0; num1<SIDES; num1++){
				if(counts[num1] > 1){
					for(num2=0; num2<dice_rolled; num2++){
						if(gs.Dice_Values[num2] == num1+1)
							gs.Dice_Selected[num2] = 1;
					}
				}
			}
			gs.rdc = gs.Dice;
			return gs.Three_Pairs_Score;
		}
	}

	//decide what dice to keep/roll or to end turn here
	if(pd[gs.Cur_Player].onboard != 1){
		if(Score < gs.Min_Get_Onboard){
			//must keep rolling
			return Select_Best(counts, scores, dice_rolled);
		}
	}
	if(Score < pd[gs.Cur_Player].min_score_will_keep){
		//must keep rolling
		return Select_Best(counts, scores, dice_rolled);
	}
	return 0;
}

static uint32_t Select_Best(uint8_t *counts, uint32_t *scores, uint8_t dice_rolled){
	uint8_t num1 = 0;
	uint8_t num2 = 0;
	//have 3+ of kind ?
	for(num2=0; num2<SIDES; num2++){
		if(counts[num2] > 2){ //FIXME: for more than 6 dice
			//dice_left = dice_rolled - counts[num2];
			//mark them
			for(num1=0; num1<dice_rolled; num1++){
				if(gs.Dice_Values[num1] == num2+1){
					gs.Dice_Selected[num1] = 1;
				}
			}
			gs.rdc = dice_rolled - counts[num2];
			return scores[num2];
		}
	}
	//keep only a 1 to increase probabilities?
	if(counts[0] != 0){ //we have a 1
		if(counts[0] < 3){ //we have less than 1000
			//keep just 1
			//dice_left = dice_rolled - 1;
			for(num1=0; num1<dice_rolled; num1++){
				if(gs.Dice_Values[num1] == 1){
					gs.Dice_Selected[num1] = 1;
					break;
				}
			}
			gs.rdc = dice_rolled - 1;
			return 100;
		}
		//keep them all (two 1's)
		gs.rdc = dice_rolled - counts[0];
		for(num1=0; num1<dice_rolled; num1++){
			if(gs.Dice_Values[num1] == 1)
				gs.Dice_Selected[num1] = 1;
		}
		return scores[0];
	}
	//have only a 5 ?
	if(counts[4] != 0){ //we have a 5
		//if(counts[4] < 3){ //we have less than 500
			//keep just 1
		//dice_left = dice_rolled - 1;
		for(num1=0; num1<dice_rolled; num1++){
			if(gs.Dice_Values[num1] == 5){
				gs.Dice_Selected[num1] = 1;
				break;
			}
		}
		gs.rdc = dice_rolled - 1;
		return 50;
		//}
		//pd[gs.Cur_Player].rdc = dice_left;
		//return 50;
		//keep them all
		//pd[gs.Cur_Player].rdc = dice_rolled - counts[4];
		//for(num1=0; num1<dice_rolled; num1++){
		//	if(gs.Dice_Values[num1] == 5)
		//		gs.Dice_Selected[num1] = 1;
		//}
		//return scores[4];
	}
	//FIXME: function return value for main cleanup ie: errno
	printf("Error 1 !\n");
	//exit(0);
	return 0;
}



/*
	}
	if(Score < pd[p_num].min_score_will_keep){
		//must keep rolling
		for(num2=0; num2<SIDES; num2++){
			if(counts[num2] > 2){//FIXME: for more than 6 dice
				//dice_left = dice_rolled - counts[num2];
				for(num1=0; num1<dice_rolled; num1++){
					if(gs.Dice_Values[num1] == num2+1)
						gs.Dice_Selected[num1] = 1;
				}
				pd[gs.Cur_Player].rdc = dice_rolled - counts[num2];
				return scores[num2];
			}
		}
		if(counts[0] != 0){
			if(num_counts[0] < 3){
				rolling_dice = dice_rolled - 1;
				score_final += 100;
				continue;
			}
			rolling_dice = dice_rolled - num_counts[0];
			score_final += num_scores[0];
			continue;
		}
		if(num_counts[4] != 0){
			rolling_dice = dice_rolled - 1;
			score_final += 50;
			continue;
		}
		//FIXME: see above
		printf("Error 2 !\n");
		exit(0);
	}else{
		turn_not_over = 0;
	}


	if( rolling_dice < pd[p_num].min_dice_will_roll){
		//will keep rolling if new rolling_dice value is not too low
		//take score and end turn
		turn_not_over = 0;
	}
	score_final += score;
}
*/

//	free(roll_results);
//	free(kept_dice);
//	return score_final;
//}

/*
void *Worker_Func(void *data){
	uint32_t num1, num2;
	uint32_t turn = 0;
	uint8_t ten_k_reached = 0;
	uint32_t tentative_winner = 0;
	uint32_t leader_score = 0;
	
	struct timeval cur;
	gettimeofday(&cur, NULL);
	//pd = (struct Player_Data *)malloc(sizeof(struct Player_Data) * Num_Players);

	while(1==1){
		sleep(1);
		
		if(gs.Exit_Program)
			break;
	}
	//free(pd);
	//pthread_exit(NULL);
	return NULL;
}

uint32_t Score_Of_Selection(void){
	//return the score of currently selected dice
	//call from any selection activity callback
	//maybe use for AI too
	uint32_t Score = 0;
	uint8_t num1 = 0;
	uint8_t num2 = pd[gs.Cur_Player].rdc;
	for(num1=0; num1<num2; num1++){
		if(gs.Dice_Selections[num1] == 1){
			
		}
	}


}
*/


uint8_t Valid_Dice_Selection(void){
	//return TRUE if selected dice are valid and it is OK for a LOCAL_PLAYER to roll
	//all selected dice must contribute to points
	//If FALSE then Dice_Selections must be reset, and user given another chance to select properly

	//Function Don't edit any objects outside of itself

    uint8_t dice_rolled = gs.rdc;
    //uint8_t *dice_tmp = (uint8_t *)malloc(sizeof(uint8_t)*dice_rolled);
    uint8_t counts[SIDES];
    //uint32_t scores[SIDES];
    uint8_t num1 = 0;
    //uint8_t num2 = 0;



	//uint8_t num1 = 0;
	//uint8_t num2 = 0;
	uint8_t dice_selected = 0;
	//uint8_t um_counts[SIDES];
	for(num1=0; num1<dice_rolled; num1++){
		if(gs.Dice_Selected[num1] == 1)
			dice_selected++;
	}
	if(dice_selected == 0)
		return FALSE;
	uint8_t *dice_tmp = (uint8_t *)malloc(sizeof(uint8_t)*dice_selected);
	dice_selected = 0;
	for(num1=0; num1<dice_rolled; num1++){
		if(gs.Dice_Selected[num1] == 1){
			dice_tmp[dice_selected] = gs.Dice_Values[num1];
			dice_selected++;
		}
	}

	if(dice_selected == gs.Dice){
		if(Has_Straight(dice_tmp, dice_selected))
			return TRUE;
	}
	Gen_Num_Counts(dice_tmp, counts, dice_selected);
	if(dice_selected > 5){
		if(Has_Three_Pair(counts, dice_selected))
			return TRUE;
	}

	//has x of kind
	for(num1=0; num1<SIDES; num1++){
		if(counts[num1] != 0){
			if(num1 == 0) //1
				continue;
			if(num1 == 4) //5
				continue;
			if(counts[num1] < 3) //less than 3 of kind
				return FALSE;
		}
	}

	free(dice_tmp);
	return TRUE;
}
