Exemple #1
0
/*
 * Trims the list of possible jump moves, so it only contains moves that result in the maximum amount of captures
 *
 * @params: (jumpMovesList) - the list of all possible jump moves
 * @return: a trimmed list, or NULL if any allocation errors occurred 
 */
static struct LinkedList* trimJumpMovesList (struct LinkedList* jumpMovesList){
	int maxCaptures = 0;
	
	//finding the maximum number of captures in a currently possible jump move
	struct Iterator iterator;
	Iterator_init(&iterator, jumpMovesList);
	while(Iterator_hasNext(&iterator)){ 
		struct PossibleMove* currMove = (struct PossibleMove*)(Iterator_next(&iterator));
		int currNumOfCaptures = PossibleMove_numOfCaptures(currMove);
		if(currNumOfCaptures > maxCaptures){
			maxCaptures = currNumOfCaptures;
		}
	}			
	
	//creating a new list and filling it only with the appropriate moves
	struct LinkedList* trimmedJumpMoves = LinkedList_new(&PossibleMove_free);
	if(trimmedJumpMoves == NULL){ // allocation failed
		return NULL;
	}
	struct Iterator secondIterator;
	Iterator_init(&secondIterator, jumpMovesList);
	while(Iterator_hasNext(&secondIterator)){
		struct PossibleMove* currMove = (struct PossibleMove*)(Iterator_next(&secondIterator));
		if(PossibleMove_numOfCaptures(currMove) == maxCaptures){
			struct PossibleMove* clonedCurrMove = PossibleMove_clone(currMove);
			if (clonedCurrMove == NULL){ // allocation failed
				LinkedList_free(trimmedJumpMoves);
				return NULL;
			}
			LinkedList_add(trimmedJumpMoves, clonedCurrMove);
		}
	}
	LinkedList_free(jumpMovesList);
	return trimmedJumpMoves;		
}
int printBestMoves(char* command){
	int depth;
	if (command[15] == 'b'){
		depth = computeBestDepth();
	}
	else{
		if (sscanf(command, "get_best_moves %d", &depth) != 1){
			return -1;
		}
	}
	
	LinkedList* allPossibleMoves = Board_getPossibleMoves(&board, turn);
	if (!allPossibleMoves){
		return 1;
	}
	int bestScore = INT_MIN;
	Iterator iterator;
	Iterator_init(&iterator, allPossibleMoves);
	LinkedList* bestMoves = PossibleMoveList_new();
	if (!bestMoves){
		PossibleMoveList_free(allPossibleMoves);
		return 1;
	}
	while(Iterator_hasNext(&iterator)){
		PossibleMove* currentMove = (PossibleMove*)Iterator_next(&iterator);
		int score = alphabeta(currentMove, depth, !turn, INT_MIN, INT_MAX);
		if (score > bestScore) {
			LinkedList_removeAll(bestMoves);
			if(LinkedList_add(bestMoves, currentMove)){
				LinkedList_removeAll(bestMoves);
				LinkedList_free(bestMoves);
				PossibleMoveList_free(allPossibleMoves);
				return 1;
			}
			bestScore = score;
		}
		else if (score == bestScore){
			if(LinkedList_add(bestMoves, currentMove)){
				LinkedList_removeAll(bestMoves);
				LinkedList_free(bestMoves);		
				PossibleMoveList_free(allPossibleMoves);
				return 1;
			}
		}
	}
	PossibleMoveList_print(bestMoves);
	LinkedList_removeAll(bestMoves);	//removes the nodes
	LinkedList_free(bestMoves);			//frees the struct
	LinkedList_free(allPossibleMoves);	//frees the moves
	return 0;
}
/*
LinkedList* getRedirectionQueue()
	Description:
		Creates a queue that can be iterated through using _next()
	args:
		char** args
			Array of tokens
	return:
		LinkedList reverse so that _next() iterates through in order of args.
		Args are grouped with redirects in the middle of them.
		Returns NULL if not a proper redirection.
*/
LinkedList* getRedirectionQueue(char** args){
	if(!isProperRedirection(args)){
		return NULL;
	}
	LinkedList* stack = LinkedList_init();
	LinkedList* output = LinkedList_init();

	int j = 0;
	char** buffer = calloc(128, sizeof(*buffer));
	for(int i = 0; args[i] != NULL; i++){
		if(args[i][0] != '>' && args[i][0] != '<'){
			buffer[j] = args[i];					//Start collecting args
			j++;
		}else{										//Redirect detected. Queue.
			LinkedList_queue(stack, buffer);
			
			char** redirect = calloc(1,sizeof(*redirect));			//Add the redirect symbol to the queue
			redirect[0] = args[i];
			LinkedList_queue(stack, redirect);
			
			j = 0;
			buffer = calloc(128, sizeof(*buffer));				//Make new args collector
		}
	}
	if(buffer){
		LinkedList_queue(stack, buffer);				//Edge case. Final queue
	}
	output = LinkedList_reverse(stack);				//Reverse stack to get queue
	LinkedList_free(stack);
	return output;
}
LinkedList* getPipeQueue(char** args){
	if(!isProperPipe(args)){
		return NULL;
	}
	LinkedList* stack = LinkedList_init();
	LinkedList* output = LinkedList_init();
	
	int j = 0;
	char** buffer = calloc(128, sizeof(*buffer));
	for(int i = 0; args[i] != NULL; i++){
		if(args[i][0] != '|'){
			buffer[j] = args[i];					//Start collecting args
			j++;
		}else{										//Pipe detected. Queue.
			LinkedList_queue(stack, buffer);
			
			char** pipeline = calloc(1,sizeof(*pipeline));			//Add the pipeline symbol to the queue
			pipeline[0] = args[i];
			LinkedList_queue(stack, pipeline);
			j = 0;
			buffer = calloc(128, sizeof(*buffer));				//Make new args collector
		}
	}
	if(buffer){
		LinkedList_queue(stack, buffer);				//Edge case. Final queue
	}
	output = LinkedList_reverse(stack);				//Reverse stack to get queue
	LinkedList_free(stack);
	
	return output;

}
Exemple #5
0
/*
 * Main function for getting all of the moves currently possible for a player. 
 *
 * @params: (player) - the player whose moves are to be put in the list
 * @return: a list of all moves currently possible for the player, or NULL if any allocation errors occurred 
 */
struct LinkedList* Board_getPossibleMoves(char** board, int player){
	struct LinkedList* possibleJumpMoves = getPossibleJumps(board, player);
	if (possibleJumpMoves == NULL){ // allocation failed
		return NULL;
	}
	if (LinkedList_length(possibleJumpMoves) != 0){ /* if jumps are possible, they are the only type of move legally possible */
		struct LinkedList* trimmedJumpMoves = trimJumpMovesList(possibleJumpMoves);
		if(trimmedJumpMoves == NULL){ // allocation failed
			LinkedList_free(possibleJumpMoves);
			return NULL;
		}
		return trimmedJumpMoves;
	}
	LinkedList_free(possibleJumpMoves);
	struct LinkedList* singleMoves = getPossibleSingleMoves(board, player);
	if (singleMoves == NULL){ // allocation failed
		return NULL;
	}
	
	return singleMoves;
}	
Exemple #6
0
/*
 * Retrieves a list of all jump moves currently possible for a player.
 *
 * @params: (player) - the player whose moves are to be put in the list
 * @return: a LinkedList struct of jump moves currently possible for the player, or NULL if any allocation errors occurred
 */
static struct LinkedList* getPossibleJumps (char** board, int player){
	struct LinkedList* jumpMoves = LinkedList_new(&PossibleMove_free);
	if(jumpMoves == NULL){ //allocation failed
		return NULL;
	}
	
	for (int x = 1; x <= Board_SIZE; x++){
		for (int y = 1; y <= Board_SIZE; y++){			
			if (Board_evalPiece(board, x, y, player) <= 0){
				continue;
			}
			for (int i = -1; i <= 1; i += 2){
				for (int j = -1; j <= 1; j += 2){
					struct Tile* destTile = NULL;
					if (!isInRange(x+i,y+j) || !isInRange(x+2*i,y+2*j)){
						continue;
					}
					int pieceIsKing = Board_evalPiece(board, x, y, player) == 3;
					if (pieceIsKing){
						destTile = canKingCaptureInDirection(board, x, y, i, j);
					}
					else{
						int enemyNearby = Board_evalPiece(board, x+i, y+j, player) < 0;
						int enemyIsCapturable = Board_isEmpty(board, x+2*i, y+2*j);
						if(enemyNearby && enemyIsCapturable){
							destTile = Tile_new(x+2*i, y+2*j);
							if (destTile == NULL){ // allocation failed
								return NULL;
							}
						}
					}
					if (!destTile){
						continue;
					}
					struct LinkedList* jumpSteps = LinkedList_new(&Tile_free);
					if (jumpSteps == NULL){ // allocation failed
						Tile_free(destTile);
						return NULL;
					}
					LinkedList_add(jumpSteps, destTile);
					struct PossibleMove* possibleJumpMove = PossibleMove_new(x, y, jumpSteps, board);
					if (possibleJumpMove == NULL){ // allocation failed
						Tile_free(destTile);
						LinkedList_free(jumpSteps);
						return NULL;
					}
					populateJumpList(jumpMoves, possibleJumpMove);
				}
			}
		}	
	}
	return jumpMoves;
}
int leftMouseButtonUp(SDL_Event e){
	convertPixelsToBoardPosition(e, &selectedX, &selectedY);
	if (movesOfSelectedPiece){
		LinkedList_free(movesOfSelectedPiece);
		movesOfSelectedPiece = NULL;
	}
	movesOfSelectedPiece = Board_getPossibleMovesOfPiece(&board, selectedX, selectedY, 0);
	if (!movesOfSelectedPiece){
		return 1;
	}
	
	return 0;
}
Exemple #8
0
/*
 * Gets a list of all single step moves currently possible for a player.
 *
 * @params: (player) - the player whose moves are to be put in the list
 * @return: a list of single step moves currently possible for the player, or NULL if any allocation errors occurred 
 */
static struct LinkedList* getPossibleSingleMoves (char** board, int player){
	struct LinkedList* possibleSingleMoves = LinkedList_new(&PossibleMove_free);
	if (possibleSingleMoves == NULL){
		return NULL;
	}
	int forward = (player == BLACK) ? -1 : 1; /* for each player's different direction of "forward" */
	for (int x = 1; x <= Board_SIZE; x++){
		for (int y = 1; y <= Board_SIZE; y++){
			if (Board_evalPiece(board, x, y, player) <= 0){ //this tile doesn't contain one of this player's pieces
				continue;
			} 
			for (int sideward = -1; sideward <= 1; sideward += 2){
				for (int k = -Board_SIZE; k <= Board_SIZE; k++){
					if (!isInRange(x+k*sideward, y+k)){
						continue;
					}	
					int pieceIsKing = Board_evalPiece(board, x, y, player) == 3;
					if (!pieceIsKing && k != forward){
						continue;
					}	
					if(Board_isEmpty(board, x+k*sideward, y+k)){
						struct Tile* destTile = Tile_new(x+k*sideward, y+k);
						if (destTile == NULL){ // allocation failed
							return NULL;
						}
						struct LinkedList* singleSteps = LinkedList_new(&Tile_free);
						if (singleSteps == NULL){ // allocation failed
							Tile_free(destTile);
							return NULL;
						}
						LinkedList_add(singleSteps, destTile);
						struct PossibleMove* possibleSingleMove = PossibleMove_new(x, y, singleSteps, board);
						if (possibleSingleMove == NULL){ // allocation failed
							Tile_free(destTile);
							LinkedList_free(singleSteps);
							return NULL;
						}
						LinkedList_add(possibleSingleMoves, possibleSingleMove);
					}
					if (!pieceIsKing && k == forward){
						break;
					}
				}
			}
		}
	}
	return possibleSingleMoves;
}
int setSelectedMoveToBest(){
	if (movesOfSelectedPiece){
		LinkedList_free(movesOfSelectedPiece);
	}
	movesOfSelectedPiece = LinkedList_new(&PossibleMove_free);
	if (!movesOfSelectedPiece){
		return -1;
	}
	PossibleMove* bestMove = getBestMove();
	if (!bestMove){
		return -1;
	}
	selectedX = bestMove->fromX;
	selectedY = bestMove->fromY;
	if(LinkedList_add(movesOfSelectedPiece, bestMove)){
		return -1;
	}
	
	return 0;
}
/*
 * The minimax AI algorithm.
 */
int alphabeta(PossibleMove* possibleMove, int depth, int player, int alpha, int beta){
	int (*evaluationFunction)(Board*, int, int) = (maxRecursionDepth == BEST)?
				&Board_getBetterScore:
				&Board_getScore;
	int thisBoardScore = evaluationFunction(possibleMove->board, turn, player);
	// maximum depth reached or game is over or allocation error occurred in Board_getScore
	if (depth == 1 || thisBoardScore == 10000 || thisBoardScore == -10000 || thisBoardScore == -10001){
		return thisBoardScore;
	}
	
	Board* board = possibleMove->board;
	LinkedList* possibleMoves = Board_getPossibleMoves(board, player);
	if (!possibleMoves){
		return -10001;
	}
	//terminal node
	if (LinkedList_length(possibleMoves) == 0){
		LinkedList_free(possibleMoves);
		return thisBoardScore;
	}
	//single child node
	if (LinkedList_length(possibleMoves) == 1){
		PossibleMove* onlyMove = PossibleMoveList_first(possibleMoves);
		int score = evaluationFunction(onlyMove->board, turn, player);
		LinkedList_free(possibleMoves);
		return score;
	}

	int extremum = (player == turn)? INT_MIN : INT_MAX;
	Iterator iterator;
	Iterator_init(&iterator, possibleMoves);
	while (Iterator_hasNext(&iterator)) {
		PossibleMove* currentPossibleMove = (PossibleMove*)Iterator_next(&iterator);
		int score = alphabeta(currentPossibleMove, depth-1, !player, alpha, beta);
		if (score == -10001){ //allocation error occured
			extremum = score;
			break;
		}
		if (	(player != turn && score <  extremum) || 
				(player == turn && score >  extremum) || 
				(rand()%2       && score == extremum)
			){
			extremum = score;
		}
		//game over - no need to evaluate further moves
		// if (extremum == 10000 || extremum == -10000){
			// break;
		// }
		//alpha-beta pruning
		if (turn == player){
			alpha = (score > alpha)? score: alpha;
			if (alpha >= beta){
				break;
			}	
		}
		else{
			beta = (score < beta)? score: beta;
			if (beta <= alpha){
				break;
			}
		}

	}
	LinkedList_free(possibleMoves);
	return extremum;
}