#include "GadTicTacToe.h"
/*
	Codes on board
	O = opponent's space
	X = my space
	M = my choice of move
	A = opponent's assumed next move
	P = my previous move of a strategy
	1 = My first choice of move
	2 = My second choice of move
*/

void 
GadTicTacToe::init(char p1C, char p2C, bool p1H, bool p2H, int diffP1, int diffP2) {
	srand((unsigned)time(0));
	player1Char = p1C;
	player2Char = p2C;
	p1IsHuman = p1H;
	p2IsHuman = p2H;
	whoseTurn = whoStarts;
	turnCounterTotal = 0;
	turnCounterPlayer1 = 0;
	turnCounterPlayer2 = 0;
	p1NextMove = -1;
	p2NextMove = -1;
	falterChanceP1 = diffP1;
	falterChanceP2 = diffP2;
	howManyFaltersP1=0;
	howManyFaltersP2=0;
	for(int j = 0; j < 9; j++)
		board[j] = ' ';
}
int 
GadTicTacToe::computeNextMove(char myC, bool falter, int diff)	{

	int rFalt;
	if(diff == 0)
		diff = RAND_MAX;

	if(board[4] == ' ')
		return 4;
	
	int index = -1;
	char hisC;
	if(myC == player1Char)		// determines which player 
		hisC = player2Char;		// computer is playing for
	else
		hisC = player1Char;
	
	index = emminent(myC);		// checks for emminent win
	if(index != -1)
		return index;

	rFalt = rand()%3*diff;
	if(rFalt != 1 && falter)
	{
		index = emminent(hisC);		// checks for emminent loss
		if(index != -1)
			return index;
	}

	index = checkForNextMove(myC);
	if(index != -1)
		return index;

	rFalt = rand()%(1+diff);
	if(rFalt != 1 && falter && turnCounterTotal <= 2)
	{
		index = secondMove(hisC);
		if(index != -1)
			return index;
	}

	rFalt = rand()%(1+diff);
	if(rFalt != 1 && falter)
	{
		index = checkForSides(hisC);
		if(index != -1)
			return index;
	}

	rFalt = rand()%(1+diff);
	if(rFalt != 1 && falter)
	{
		index = checkForCornerSides(hisC);
		if(index != -1)
			return index;
	}

	rFalt = rand()%(1+diff);
	if(rFalt != 1 && falter)
	{
		index = checkForCorners(hisC);
		if(index != -1)
			return index;
	}

	index = checkForFreeMove();
	if(index != -1)
		return index;

	return -1;
}

// Checks for emminent win/loss
int
GadTicTacToe::emminent(char C) {
	for(int j = 0; j < 3; j++)
	{
		if(board[3*j] == C && board[3*j+1] == C && board[3*j+2] == ' ')
			return 3*j+2;
		if(board[3*j] == C && board[3*j+2] == C && board[3*j+1] == ' ')
			return 3*j+1;
		if(board[3*j+1] == C && board[3*j+2] == C && board[3*j] == ' ')
			return 3*j;

		if(board[j] == C && board[j+3] == C && board[j+6] == ' ')
			return j+6;
		if(board[j] == C && board[j+6] == C && board[j+3] == ' ')
			return j+3;
		if(board[j+3] == C && board[j+6] == C && board[j] == ' ')
			return j;
	}
	
	if(board[0] == C && board[4] == C && board[8] == ' ')
		return 8;
	if(board[0] == C && board[8] == C && board[4] == ' ')
		return 4;
	if(board[8] == C && board[4] == C && board[0] == ' ')
		return 0;

	if(board[2] == C && board[4] == C && board[6] == ' ')
		return 6;
	if(board[2] == C && board[6] == C && board[4] == ' ')
		return 4;
	if(board[6] == C && board[4] == C && board[2] == ' ')
		return 2;
	else 
		return -1;
}

// Checks to see if offensive strategy in play
// strategy initiated from secondMove()
int 
GadTicTacToe::checkForNextMove(char C) {
	int returnThis;
	if(C == player1Char && p1NextMove != -1)
	{
		returnThis = p1NextMove;
		p1NextMove = -1;
		return returnThis;
	}
	if(C == player2Char && p2NextMove != -1)
	{
		returnThis = p2NextMove;
		p2NextMove = -1;
		return returnThis;
	}
	return -1;
}


/*
	 |M| 
	-----
	 |X|O
	-----
	 | |
*/
int 
GadTicTacToe::secondMove(char C) {
	int index = -1;
	int randomNumber = rand()%2;
	if(board[1] == C)
	{
		if(randomNumber == 0)
			index = 5;
		else 
			index = 3;
	}
	else if(board[5] == C)
	{
		if(randomNumber == 0)
			index = 7;
		else 
			index = 1;
	}

	else if(board[7] == C)
	{
		if(randomNumber == 0)
			index = 3;
		else
			index = 5;
	}
	else if(board[3] == C)
	{
		if(randomNumber == 0)
			index = 1;
		else
			index = 7;
	}

	if(index != -1 && C == player1Char)
		p2NextMove = nextMove(C, index);
	else if(index != -1 && C == player2Char)
		p1NextMove = nextMove(C, index);

	else if(board[0] == C)
		index = 8;
	else if(board[2] == C)
		index = 6;
	else if(board[6] == C)
		index = 2;
	else if(board[8] == C)
		index = 0;

	return index;
}

/*
	 |O|M
	-----
	 | |O
	-----
	 | |
*/
int 
GadTicTacToe::checkForSides(char C) {
	if(board[1] == C)
	{
		if(board[5] == C && board[2] == ' ')
			return 2;
		if(board[3] == C && board[0] == ' ')
			return 0;
	}
	if(board[7] == C)
	{
		if(board[5] == C && board[8] == ' ')
			return 8;
		if(board[3] == C && board[6] == ' ')
			return 6;
	}
	return -1; 
}
/*
	O| | 
	-----
	 | |O
	-----
	 |M|
*/
int 
GadTicTacToe::checkForCornerSides(char C) {
	if(board[0] == C)
	{
		if(board[5] == C && board[7] == ' ')
			return 7;
		if(board[7] == C && board[5] == ' ')
			return 5;
	}
	if(board[2] == C)
	{
		if(board[3] == C && board[7] == ' ')
			return 7;
		if(board[7] == C && board[3] == ' ')
			return 3;
	}
	if(board[6] == C)
	{
		if(board[5] == C && board[1] == ' ')
			return 1;
		if(board[1] == C && board[5] == ' ')
			return 5;
	}
	if(board[8] == C)
	{ 
		if(board[3] == C && board[1] == ' ')
			return 1;
		if(board[1] == C && board[3] == ' ')
			return 3;
	}
	return -1;
}

/*
	O| |
	-----
	 |X|M
	-----
	 | |O
*/
int
GadTicTacToe::checkForCorners(char C) {
	if(board[0] == C)
	{
		if(board[8] == C)
		{
			if(board[1] == ' ')
				return 1;
			if(board[5] == ' ')
				return 5;
		}
		if(board[2] == C)
		{
			if(board[8] == ' ')
				return 8;
			if(board[6] == ' ')
				return 6;
		}
		if(board[6] == C)
		{
			if(board[8] == ' ')
				return 8;
			if(board[2] == ' ')
				return 2;
		}
	}	
	if(board[2] == C)
	{
		if(board[8] == C)
		{
			if(board[0] == ' ')
				return 0;
			if(board[6] == ' ')
				return 6;
		}
		if(board[6] == C)
		{
			if(board[1] == ' ')
				return 1;
			if(board[5] == ' ')
				return 5;
		}
		if(board[0] == C)
		{
			if(board[8] == ' ')
				return 8;
			if(board[6] == ' ')
				return 6;
		}
	}
	return -1;
}

/*
	 |P|M
	-----
	 |X|O
	-----
	 |A|
*/
int
GadTicTacToe::nextMove(char C, int s) {
	if(s == 5)
	{
		if(board[7] == C)
			return 2;
		if(board[1] == C)
			return 8;
	}
	if(s == 1)
	{
		if(board[3] == C)
			return 2;
		if(board[5] == C)
			return 0;
	}
	if(s == 3)
	{
		if(board[1] == C)
			return 6;
		if(board[7] == C)
			return 0;
	}
	if(s == 7)
	{
		if(board[3] == C)
			return 8;
		if(board[5] == C)
			return 6;
	}
	return -1;
}

//Takes first available corner then first available space
int 
GadTicTacToe::checkForFreeMove() {
	if(board[0] == ' ')
		return 0;
	if(board[2] == ' ')
		return 2;
	if(board[6] == ' ')
		return 6;
	if(board[8] == ' ')
		return 8;
	for(int j = 0; j < 9; j++)
		if(board[j] == ' ')
			return j;
	return -1;
}








bool 
GadTicTacToe::player1TakeATurn(int index) {

	if(enforceMove(index, player1Char) == false)
		return false;
	turnCounterTotal +=1;
	turnCounterPlayer1 +=1;
	return true;
}
bool 
GadTicTacToe::player2TakeATurn(int index) {

	if(enforceMove(index, player2Char) == false)
		return false;
	turnCounterTotal +=1;
	turnCounterPlayer2 +=1;
	return true;
}



bool 
GadTicTacToe::player1TakeATurn() {
	if(!p1IsHuman)
	{
		computerMove(player1Char, falterChanceP1);
		turnCounterTotal +=1;
		turnCounterPlayer1 +=1;
		return true;
	}
	int index;
	do{
		index = -1;
		printBoardForHuman();
		cout << "Move " << turnCounterTotal << endl;
		cout << "Player 1 -> Please make a move  (HINT: " << getAClue(player1Char) << ")" << endl;
		cin >> index;
		system("cls");
	}while(enforceMove(index, player1Char) == false);
		
	turnCounterTotal +=1;
	turnCounterPlayer1 +=1;
	return true;
}
bool 
GadTicTacToe::player2TakeATurn() {
	if(!p2IsHuman)
	{
		computerMove(player2Char, falterChanceP2);
		turnCounterTotal +=1;
		turnCounterPlayer2 +=1;
		return true;
	}
	int index;
	do{
		index = -1;
		printBoardForHuman();
		cout << "Player 2 -> Please make a move  (HINT: " << getAClue(player2Char) << ")" << endl;
		cin >> index;
		system("cls");
	}while(enforceMove(index, player2Char) == false);
		
	turnCounterTotal +=1;
	turnCounterPlayer2 +=1;
	return true;
}
bool 
GadTicTacToe::computerMove(char C, int falterChance) {
	enforceMove(computeNextMove(C, true, falterChance), C);
	turnCounterTotal +=1;
	turnCounterPlayer1 +=1;
	return true;
}
int
GadTicTacToe::getAClue(char C) {
	return convertFromComputerToHuman(computeNextMove(C,false, 10));
}








void 
GadTicTacToe::nextTurn() {
	if(whoseTurn%2 == 0)
		player1TakeATurn();
	else
		player2TakeATurn();
	whoseTurn++;
}
bool 
GadTicTacToe::isItFinished() {
	if(didPlayer1Win() == true || didPlayer2Win() == true || isBoardFull() == true)
		return true;
	return false;
}
bool 
GadTicTacToe::didSomeoneWin(char C) {
	int j = 0;
	for(j = 0; j < 3; j++)
	{
		if(board[3*j] == C && board[3*j+1] == C && board[3*j+2] == C) 
			return true;
		if(board[j] == C && board[j+3] == C && board[j+6] == C) 
			return true;
	}
	if(board[0] == C && board[4] == C && board[8] == C) 
		return true;
	if(board[2] == C && board[4] == C && board[6] == C) 
		return true;
	return false;
}
bool 
GadTicTacToe::didPlayer1Win() {
	if(didSomeoneWin(player1Char))
		return true;
	return false;
}
bool 
GadTicTacToe::didPlayer2Win() {
	if(didSomeoneWin(player2Char))
		return true;
	return false;
}

bool 
GadTicTacToe::enforceMove(int index, char C) {
	bool isHuman = false;
	if(C == player1Char && p1IsHuman)
		isHuman = true;
	if(C == player2Char && p2IsHuman)
		isHuman = true;

	int newIndex = index;
//	if(isHuman)
//		newIndex = convertFromHumanToComputer(index);
	if(board[newIndex] == ' ')
	{
		board[newIndex] = C;
		return true;
	}
	return false;
}
bool 
GadTicTacToe::isBoardFull() {
	for(int j = 0; j < 9; j++)
		if(board[j] == ' ')
			return false;
	return true;
}

int 
GadTicTacToe::convertFromHumanToComputer(int a) {
		switch(a)
		{
			case 1: return 6; break;
			case 2: return 7; break;
			case 3: return 8; break;
			case 4: return 3; break;
			case 5: return 4; break;
			case 6: return 5; break;
			case 7: return 0; break;
			case 8: return 1; break;
			case 9: return 2; break;
			default:return 0; break;
		}
		return 0;
}

int 
GadTicTacToe::convertFromComputerToHuman(int a) {
		switch(a)
		{

			case 0: return 7; break;
			case 1: return 8; break;
			case 2: return 9; break;
			case 3: return 4; break;
			case 4: return 5; break;
			case 5: return 6; break;
			case 6: return 1; break;
			case 7: return 2; break;
			case 8: return 3; break;
			default:return 0; break;
		}
		return 0;
}

void 
GadTicTacToe::printBoard() {
	cout << endl << endl;
	cout << board[0] << "|" << board[1] << "|" << board[2] << endl;
	cout << "-----" << endl;
	cout << board[3] << "|" << board[4] << "|" << board[5] << endl;
	cout << "-----" << endl;
	cout << board[6] << "|" << board[7] << "|" << board[8] << endl;
	cout << endl << endl;
}
void 
GadTicTacToe::printBoardForHuman() {
	cout << endl << endl;
	cout << board[0] << "|" << board[1] << "|" << board[2] << "      7|8|9" << endl;
	cout << "-----      -----" << endl;
	cout << board[3] << "|" << board[4] << "|" << board[5] << "      4|5|6" <<  endl;
	cout << "-----      -----" << endl;
	cout << board[6] << "|" << board[7] << "|" << board[8] << "      1|2|3" <<  endl;
	cout << endl << endl;
}

char
GadTicTacToe::getBox(int index)
{
	return board[index];

}
int
GadTicTacToe::getTurnCounter()
{
	return turnCounterTotal;

}