#include <iostream>
using namespace std;

#include "ai.h"
#include <cmath>
#include <windows.h>

ai::ai() {
	active=false;
	myIQ=(rand()%40)+60;
}
void ai::activate(int playerNum) {
	active=true;
	myPlayerNum=playerNum;
	cout << "\nHi, I'm AI with an IQ of " << myIQ << " may the best player win!\n";
	Sleep(2000);
}

coord ai::makeMove(gameBoard & theBoard) 
{
	int r,c;
	bool moveMade=false;

	cout << "\nMy Turn...\n";

	myChoice.row=-1;
	myChoice.col=-1;

	// take a look at the current state of the board
	//(load the game board into my imagination so I can play with different possible moves)
	myImaginaryBoard=theBoard;

	// can I win this turn?
	if ( smartMove() ) {
		if ( instaWin() ) {
			// myChoice was altered by instaWin
			moveMade=true;
		}
	}

	// try blocking
	if ( !moveMade && smartMove() ) {
		if ( tryBlock() ) {
			// myChoice was altered by tryBlock
			moveMade=true;
		}
	}

	if ( !moveMade ) {
		// list possible cells
		vector<coord> possibleChoices;
		coord thisCell;

		for ( r=0; r < ROWS; r++ ) {
			for ( c=0; c < COLS; c++ ) {
				if ( myImaginaryBoard.cellIsEmpty(r,c) ) { 
					thisCell.row=r;
					thisCell.col=c;
					thisCell.score=0;
					possibleChoices.push_back(thisCell);
				}
			}
		}

		// if smart, I'll score each possible move
		if ( smartMove() ) { scorePossibles(possibleChoices); }
		
		// what's left are the choices with the best score, choose one at random
		int rndChoice=rand()%possibleChoices.size();

		myChoice=possibleChoices[rndChoice];

	} 


	//cout << "\nI Choose (" << myChoice.row << "," << myChoice.col << ")\n";
	Sleep(1500);

	//system("pause");

	return myChoice;

}
void ai::bestPossible(vector<coord> & possibleChoices) {
	// eliminates all possible choices who's score is lower than the highest score

	int bestScore=0;
	unsigned int i;
	
	vector<coord> newChoices;

	// find the best score
	for ( i=0; i < possibleChoices.size(); i++ )
	{
		if ( possibleChoices[i].score > bestScore ) { bestScore = possibleChoices[i].score; }
	}

	// build a new list of only the cells containing the best score
	for ( i=0; i < possibleChoices.size(); i++ )
	{
		if ( possibleChoices[i].score == bestScore ) 
		{
			newChoices.push_back(possibleChoices[i]);
		}
	}
	
	// copy that back to the original vector
	possibleChoices.empty();
	possibleChoices=newChoices;

}
void ai::scorePossibles(vector<coord> & possibleChoices) {
	// look at each possible move and place a score for that cell
	// score is the number of possible wins from that location

	cout << "\nDetermining the best move...\n";
	int r,c,x;
	bool lineWinable;

	for ( unsigned int i=0; i < possibleChoices.size(); i++ ) {
		// see if I can fill this row (no opponents)
		lineWinable=true;
		for ( x=0; x < COLS; x++ ) {
			r=possibleChoices[i].row;
			c=x;
			if ( !myImaginaryBoard.isCellMine(r,c,myPlayerNum) &&
				 !myImaginaryBoard.cellIsEmpty(r,c) )
				{
					lineWinable=false;
					break;
				}
		}
		if ( lineWinable ) { possibleChoices[i].score++; }


		// see if I can fill this col (no opponents)
		lineWinable=true;
		for ( x=0; x < ROWS; x++ ) {
			r=x;
			c=possibleChoices[i].col;
			if ( !myImaginaryBoard.isCellMine(r,c,myPlayerNum) &&
				 !myImaginaryBoard.cellIsEmpty(r,c) ) 
				{
					lineWinable=false;
					break;
				}
		}
		if ( lineWinable ) { possibleChoices[i].score++; }


		// if top/left, can I capture diagnal?
		lineWinable=true;
		if ( possibleChoices[i].row == 0 && possibleChoices[i].col == 0 ) {
			for ( x=0; x < ROWS; x++ ) {
				if ( !myImaginaryBoard.isCellMine(x,x,myPlayerNum) &&
					 !myImaginaryBoard.cellIsEmpty(x,x) )
				{
					lineWinable=false;
					break;
				}
			}
			if ( lineWinable ) { possibleChoices[i].score++; }
		}

		// if top/right, can I capture diagnal?
		lineWinable=true;
		if ( possibleChoices[i].row == 0 && possibleChoices[i].col == 2 ) {
			for ( x=0; x < ROWS; x++ ) {
				if ( !myImaginaryBoard.isCellMine(x,(2-x),myPlayerNum) &&
					 !myImaginaryBoard.cellIsEmpty(x,(2-x)) )
				{
					lineWinable=false;
					break;
				}
			}
			if ( lineWinable ) { possibleChoices[i].score++; }
		}

		// if bottom/left, can I capture diagnal?
		lineWinable=true;
		if ( possibleChoices[i].row == 2 && possibleChoices[i].col == 0 ) {
			for ( x=2; x >= 0; x-- ) {
				if ( !myImaginaryBoard.isCellMine(x,(2-x),myPlayerNum) &&
					 !myImaginaryBoard.cellIsEmpty(x,(2-x)) )
				{
					lineWinable=false;
					break;
				}
			}
			if ( lineWinable ) { possibleChoices[i].score++; }
		}

		// if bottom/right, can I capture diagnal?
		lineWinable=true;
		if ( possibleChoices[i].row == 2 && possibleChoices[i].col == 2 ) {
			for ( x=2; x >= 0; x-- ) {
				if ( !myImaginaryBoard.isCellMine(x,x,myPlayerNum) &&
					 !myImaginaryBoard.cellIsEmpty(x,x) )
				{
					lineWinable=false;
					break;
				}
			}
			if ( lineWinable ) { possibleChoices[i].score++; }
		}

		// if center, can I capture diagnal?
		if ( possibleChoices[i].row == 1 && possibleChoices[i].col == 1 ) {
			if ( 
				 ( myImaginaryBoard.isCellMine(0,0,myPlayerNum) || myImaginaryBoard.cellIsEmpty(0,0) ) &&
				 ( myImaginaryBoard.isCellMine(2,2,myPlayerNum) || myImaginaryBoard.cellIsEmpty(2,2) ) 
		       ) { possibleChoices[i].score++; }

			if ( 
				 (myImaginaryBoard.isCellMine(0,2,myPlayerNum) || myImaginaryBoard.cellIsEmpty(0,2)) &&
				 (myImaginaryBoard.isCellMine(2,0,myPlayerNum) || myImaginaryBoard.cellIsEmpty(2,0)) 
			   ) { possibleChoices[i].score++; }
		} // end check diags from center
	} // end for each possible cell
	
	// remove lesser choices from the list
	bestPossible(possibleChoices);

} // end function

bool ai::smartMove()
{
	if ( myIQ > rand()%100 ) 
		return true;
	else
		return false;
}

bool ai::tryBlock()
{
	cout << "\nLet's see, do I need to block you...\n";

	int e; // enemy player #
	e=myPlayerNum+1;
	e%=PLAYERS;

	for ( int r=0; r < ROWS; r++ ) {
		for ( int c=0; c < COLS; c++ ) {
			gameBoard testBoard=myImaginaryBoard;
			if ( testBoard.cellIsEmpty(r,c) ) {
				testBoard.captureCell(r,c,e);
				if ( testBoard.playerHasWon(e) ) {
					// this capture would have won the game for my oponent
					// capture it myself and exit
					cout << "\nBlock!\n";
					myChoice.row=r;
					myChoice.col=c;
					return true;
				} // end if performed a block
			} // end if cell is empty
		} // end COLS
	} // end ROWS

	cout << "\nNope...\n";
	return false;

} // end tryBlock function
bool ai::instaWin()
{
	// determine if there is one cell I can take that will instantly win me the game

	for ( int r=0; r < ROWS; r++ ) {
		for ( int c=0; c < COLS; c++ ) {
			gameBoard testBoard=myImaginaryBoard;
			if ( testBoard.cellIsEmpty(r,c) ) {
				testBoard.captureCell(r,c,myPlayerNum);
				if ( testBoard.playerHasWon(myPlayerNum) ) {
					myChoice.row=r;
					myChoice.col=c;
					return true;
				} // end if instaWin
			} // end if cell is empty
		} // end COLS
	} // end ROWS

	return false;

}
bool ai::isActive()
{
	return active;
}
