コード例 #1
0
ファイル: board.cpp プロジェクト: AarneL/Chessgame
std::vector<int> Board::possibleMoves(int index) const
{
	//check for possible moves from which the check hasn't been removed
	std::vector<int> moves = allPossibleMoves(index);

	//remove moves that would lead to Check
	int turn = board[index] % 2;
	for(int i = 0 ; i < (int) moves.size() ; i++)
	{
		Board test_board = *this;
		test_board.movePiece(index, moves[i]); //simulate move
		if(test_board.isCheck(turn)) //see if it leads to check from player on turns point of view
		{
			moves.erase(moves.begin()+i);
			i--;
		}
	}

	return moves;
}
コード例 #2
0
double AI::DLMM(boardState* nodeOrig, int depth, int QS_Depth, bool maximizingPlayer, double alpha, double beta){
	bool terminal = false;
	double newAlpha = alpha;
	double newBeta = beta;
	double newVal = alpha;
	int moverid = playerID();
	map<string, int>::iterator it1;

	if (!maximizingPlayer){
		if (moverid == 0){ moverid = 1; }
		else{ moverid = 0; }
	}
	
	vector<fakePiece> blank;
	if (kingInCheckmate(nodeOrig, moverid)){
		double retVal = calcHeuristic(moverid, nodeOrig, blank);
		return (retVal);
	}

	else if ((depth == 0 && nodeOrig->QS_State == false) || (depth == 0 && QS_Depth == 0)){
		double retVal = calcHeuristic(moverid, nodeOrig, blank);
		return (retVal);
	}

	else if (maximizingPlayer){
		newBeta = beta;
		newAlpha = alpha;
		newVal = alpha;

		possibleMovesStruct* possibleMovesMax = new possibleMovesStruct;
		allPossibleMoves(nodeOrig, possibleMovesMax, moverid);

		if (possibleMovesMax->availiableMoves.size() > 0){			
			int size = possibleMovesMax->availiableMoves.size() - 1;
			for (int i = size; i >= 0; i--){				
				boardState* nodeNew = new boardState;
				*(nodeNew) = *(nodeOrig);
				
				int fileFrom = possibleMovesMax->availiableMoves.top().fileFrom;
				int rankFrom = possibleMovesMax->availiableMoves.top().rankFrom;
				int fileTo = possibleMovesMax->availiableMoves.top().fileTo;
				int rankTo = possibleMovesMax->availiableMoves.top().rankTo;
				
				nodeNew->unofficialMove(fileFrom, rankFrom, fileTo, rankTo, moverid, 0, 2);
				
				if (depth != 0){
					newVal = DLMM(nodeNew, depth, QS_Depth - 1, false, newAlpha, newBeta);
				}
				else{
					newVal = DLMM(nodeNew, depth - 1, QS_Depth, false, newAlpha, newBeta);
				}

				if (newVal <= newAlpha){ // Fail low
					
					possibleMovesMax->availiableMoves.pop();
				}
				else if (newVal >= newBeta){ //Fail high -> prune because fail high on max
					size = -1;
					it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
					while (possibleMovesMax->availiableMoves.size() > 0){
						possibleMovesMax->availiableMoves.pop();
					}
				}
				else{ // New best value/alpha
					newAlpha = newVal;
					it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
					possibleMovesMax->availiableMoves.pop();
				}
				delete nodeNew;
			}
			delete possibleMovesMax;

			//History table updates and inserts
			int currentCount = it1->second;
			string currentString = it1->first;
			myHistoryTable.erase(currentString);
			myHistoryTable[currentString] = currentCount + 1;
			return newAlpha;
		}
		else{  
			return alpha;
		}
	}
	else{ //Min player
		newAlpha = alpha;
		newBeta = beta;
		
		if (alpha != 0){
			newBeta = alpha;
		}
		else{
			newBeta = 1000;
		}
		newVal = 0;
		possibleMovesStruct* possibleMovesMax = new possibleMovesStruct;
		allPossibleMoves(nodeOrig, possibleMovesMax, moverid);
		
		if (possibleMovesMax->availiableMoves.size() > 0){
			
			int size = possibleMovesMax->availiableMoves.size() - 1;
			for (int i = size; i >= 0; i--){
				boardState* nodeNew = new boardState;
				*(nodeNew) = *(nodeOrig);
				
				int fileFrom = possibleMovesMax->availiableMoves.top().fileFrom;
				int rankFrom = possibleMovesMax->availiableMoves.top().rankFrom;
				int fileTo = possibleMovesMax->availiableMoves.top().fileTo;
				int rankTo = possibleMovesMax->availiableMoves.top().rankTo;
				
				nodeNew->unofficialMove(fileFrom, rankFrom, fileTo, rankTo, moverid, 0, 2);
				if (depth == 0){
					newVal = DLMM(nodeNew, depth, QS_Depth - 1, true, newAlpha, newBeta);
				}
				else{
					newVal = DLMM(nodeNew, depth - 1, QS_Depth, true, newAlpha, newBeta);
				}
				
				if (newVal <= newAlpha){ // Fail low on min -> prune
					size = -1;
					it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
					while (possibleMovesMax->availiableMoves.size() > 0){
						possibleMovesMax->availiableMoves.pop();
					}

				}
				else if (newVal >= newBeta){ //Fail high on min -> dont use this one
					
					possibleMovesMax->availiableMoves.pop();
				}
				else{ //We found a new value which is lower than the highest beta
					
					newBeta = newVal;
					it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
					possibleMovesMax->availiableMoves.pop();
				}
				delete nodeNew;
			}
			delete possibleMovesMax;

			//History table updates and inserts
			int currentCount = it1->second;
			string currentString = it1->first;
			myHistoryTable.erase(currentString);
			myHistoryTable[currentString] = currentCount + 1;

			return (newBeta);
		}
		else{
			return (beta);
		}
	}


}
コード例 #3
0
void AI::IDDLMM(boardState* nodeOrig, int depth, int QS_Depth, bool maximizingPlayer, double a, double b){
	double bestVal = 0; //Tracks best heuristic values calculated yet
	int moverid = playerID(); //The player moving is us, so call playerID() to return our playerID
	int fileFromBest, rankFromBest, fileToBest, rankToBest; //The best moves to and from coordinates
	clock_t t; //Used to keep track offthe time we started at
	clock_t t2; // Used for tracking the duration of the current depth
	clock_t t3; 
	vector<double> time; //Holds the times it took for each level of depth we search in order to calculate future depths
	double estimatedTime;
	
	possibleMovesStruct* possibleMovesMax = new possibleMovesStruct;
	allPossibleMoves(nodeOrig, possibleMovesMax, moverid); //Stores all possible moves for the given boardstate into possibleMovesMax

	map<string, int>::iterator it1;
	t = clock(); //Time we start the algorithm
	
	if (possibleMovesMax->availiableMoves.size() > 0){
		for (int i = 1; i <= depth; i++){
			delete possibleMovesMax;
			possibleMovesMax = new possibleMovesStruct;
			allPossibleMoves(nodeOrig, possibleMovesMax, moverid);
			if (possibleMovesMax->availiableMoves.size() > 0){
				//Calculating time for this depth
				t2 = clock();
				for (int j = possibleMovesMax->availiableMoves.size() - 1; j >= 0; j--){
					double newVal;
					boardState* nodeNew = new boardState;
					
					*(nodeNew) = *(nodeOrig);
					
					int fileFrom = possibleMovesMax->availiableMoves.top().fileFrom;
					int rankFrom = possibleMovesMax->availiableMoves.top().rankFrom;
					int fileTo = possibleMovesMax->availiableMoves.top().fileTo;
					int rankTo = possibleMovesMax->availiableMoves.top().rankTo;

					if (!repeatedMovesLoss(fileFrom, rankFrom, fileTo, rankTo)){
						nodeNew->unofficialMove(fileFrom, rankFrom, fileTo, rankTo, moverid, 0, 2);
						newVal = DLMM(nodeNew, i - 1, QS_Depth, false, bestVal, b);
					}

					else{
						newVal = bestVal;
						possibleMovesMax->availiableMoves.pop();
					}
					if (newVal <= bestVal){
						possibleMovesMax->availiableMoves.pop();
						// Move on 
					}
					else{
						bestVal = newVal;
						it1 = myHistoryTable.find(possibleMovesMax->availiableMoves.top().historyTableVal);
						fileFromBest = fileFrom;
						rankFromBest = rankFrom;
						fileToBest = fileTo;
						rankToBest = rankTo;
						possibleMovesMax->availiableMoves.pop();		
					}
					delete nodeNew;
					possibleMovesMax->availiableMoves.pop();
				}

				//History table updates and inserts
				int currentCount = it1->second;
				string currentString = it1->first;
				myHistoryTable.erase(currentString);
				myHistoryTable[currentString] = currentCount + 1;

				/*
				// Time Heuristic area
				*/
				
				//End time for this depth -> pushes it on the time vector
				t2 = clock() - t2;

				double tempTime = ((double)t2 / CLOCKS_PER_SEC); //Time in sec
				double estTimePerNode;
				
				time.push_back(tempTime);

				double estBranch;
				if (time.size() > 3){
					for (int n = time.size() - 1; n > 2; n--){
						//Adds up the factor difference between the times
						//i.e. 15 sec turn 1 45 sec turn 2 135 sec turn 3
						// => 0+ 135/45 = 3 + 45/15 = 6 
						estBranch += time[n] / time[n - 1];
					}

					// Dividing by the number of calculations done to get us an estimated branching factor
					estBranch = (estBranch / (time.size() - 3));
					
					for (int n = time.size() - 1; n >= 2; n--){
						//Estimates the time per node by taking the time for a specific level
						// and dividing it by the branching factor ^ branch level it was at
						estTimePerNode += time[n] / (pow(estBranch, n + 1));
					}

					//Divides by the number of calculations done / the size of the time array to get an average
					estTimePerNode = (estTimePerNode / (time.size() - 2));

					// Gets the estimated time for the next layer
					estimatedTime = (estTimePerNode)* pow(estBranch, i + 1);
					
					t3 = clock() - t;
					double timeSinceStart = ((double)t3 / CLOCKS_PER_SEC);

					//If we have spent more than x seconds on this move then quit where x is a scaling value from 1 to 5 based on time left
					double timeToSpend = 4 * (double)(((players[moverid].time()) / 900)) + 1;
					if (t3 >= timeToSpend){
						i = depth + 1;
					}
					//If making the next move is estimated to take longer than x seconds for this turn then quit and return 
					// where x is a scaling value from 1 to 5 based on time left
					else if (timeSinceStart + estimatedTime >= (timeToSpend + .5)){
						i = depth + 1;
					}
					estimatedTime = 0;
					estTimePerNode = 0;
					estBranch = 0;
				}
				else{ //Used for depths < 4
					// Estimates that the time will be the time it took for this round * the number of availiable moves
					// as we assume here the branching factor will be about the same
					
					estimatedTime = (tempTime * (possibleMovesMax->availiableMoves.size()));

					t3 = clock() - t;
					double timeSinceStart = ((double)t3 / CLOCKS_PER_SEC);
					double timeToSpend = 4 * (double)(players[moverid].time() / 900) + 1;

					//If we have spent more than x seconds on this move then quit where x is a scaling value from 1 to 5 based on time left
					if (timeSinceStart >= timeToSpend){
						i = depth + 1;
					}

					//If making the next move is estimated to take longer than x seconds for this turn then quit and return 
					// where x is a scaling value from 1 to 5 based on time left 
					else if (timeSinceStart + estimatedTime >= (timeToSpend + .5)){
						i = depth + 1;
					}
				}
			}

			for (int i = 0; i < pieces.size(); i++){
				//Make the move
				if (pieces[i].file() == fileFromBest && pieces[i].rank() == 9 - rankFromBest){
					pieces[i].move(fileToBest, 9 - rankToBest, int('Q'));
					i = pieces.size();
				}
			}
		}
	}
	else{
		//Error - do an illegal move and view log
		Piece piecetoMove;
		piecetoMove = pieces[0];
		piecetoMove.move(50, 50, int('Q'));
	}
	return;
}