/* johnchess.m * * John Mirandas chess program */ #import #import // Global Variables int moveHistory [400][6]; // History for x1,y1,x2,y2,piece,piece taken if any. int moveCount = 0; int board [9][9][9]; //Represents the boards at various plys. ply[0] is the current board. int ply = 0; //During analysis represents the ply that is currently being examined. int evalScore; //Maintains returned value from evaluation function. int positionValue [7] [9] [9]; //Holds strategic board piece values for evaluation function. int pieceValue [7] = {0,300,350,500,900,13000,100}; char pieceLetter [14] = {'.', 'p', 'k', 'q', 'r', 'b', 'n' ,'.','N', 'B', 'R', 'Q', 'K', 'P' } ; char *pieceName[7] = {" ","Knight","Bishop","Rook","Queen","King","Pawn"}; char columnLetter[9] = {' ','a','b','c','d','e','f','g','h'}; int canCastle = 1; //While 1 signifies the user can still casle. int fromx, fromy, tox, toy; //Stores the possible ply 1 move being investigated. int bestfromx, bestfromy, besttox, besttoy; //Stores best move found so far. int verbose= 2; // Controls how much search status to print during play. int gameIsOn = 1; // When switched to zero, application exits. int maxPly = 5; //Stores maximum search depth. This is user configurable during play. int pruneIt = 0; //Is set to 1 during the evaluation function if an alpha beta cut off is reached. long nodesSearched; //Statistic to return to user during play. int applyPruning = 1; //Determines if alpha beta pruning is used. This is user configurable during play. int pruningRange = 19999; int applyRandom = 1; //Adds variety to game when enabled. User configurable during play. int randomValue = 0; //Random factor applied each move. int aspirationWindow = 1; //Minor variable to slighly narrow alpha beta cut offs. time_t starttime, endtime; //Used to time computer moves. int alphabeta [10]; //Maintains alpha beta cut offs for each ply, maximum of ten plys. long nodesPruned [10]; //Maintains tree cut off count at each ply, statistic for user. int counter; //General counter. int validx1, validx2, validy1, validy2, validMove; int enforceValidMoves = 1; // Switch on weather to enforce piece movement // This function calculates the strategic location and piece values for a provided chess board. int calcBoardValue () { int score = 0; int pieceScore = 0; int boardScore = 0; int x,y; // Compute score. for (y = 1; y < 9; y++) { for (x = 1; x < 9; x++) { //The next conditionals count pieces and sum their values as well as their location value. if (board[ply][x][y] < 0) { pieceScore = pieceScore + pieceValue[ abs ( board[ply][x][y] ) ]; boardScore = boardScore + positionValue [abs (board[ply] [x][y])] [x] [9-y]; } if (board[ply][x][y] > 0) { pieceScore = pieceScore - pieceValue[ board[ply][x][y] ]; boardScore = boardScore - positionValue [ board[ply] [x][y] ] [x] [y]; } } } // The following enables a bit of randomness into the game provided applyRandom is set to 1. randomValue = ((random() % 30 )- 15 ) * applyRandom; score = pieceScore + boardScore + randomValue ; return score; } // This routine sets up the piece location strategic values. void initializeStrategy (void) { int x, y; int corePiecePosition [9] [9] = { {0,0,0,0,0,0,0,0,0}, {0,-10,-33,-20,-10,-10,-20,-33,-10}, {0,-10,0,0,0,0,0,0,-10} , {0,-10,0,5,5,5,5,0,-10} , {0,-10,0,5,10,10,5,0,-10} , {0,-10,0,5,10,10,5,0,-10} , {0,-10,0,5,5,5,5,0,-10} , {0,-10,0,0,0,0,0,0,-10} , {0,-10,-10,-10,-10,-10,-10,-10,-10} }; int kingPiecePosition [9] [9] = { {0,0,0,0,0,0,0,0,0}, {0,0,20,40,-20,0,-20,40,20}, {0,-40,-40,-40,-40,-40,-40,-40,-40}, {0,-40,-40,-40,-40,-40,-40,-40,-40}, {0,-40,-40,-40,-40,-40,-40,-40,-40}, {0,-40,-40,-40,-40,-40,-40,-40,-40}, {0,-40,-40,-40,-40,-40,-40,-40,-40}, {0,-40,-40,-40,-40,-40,-40,-40,-40}, {0,-40,-40,-40,-40,-40,-40,-40,-40} }; int pawnPiecePosition [9] [9] = { {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,-31,-31,0,0,0}, {0,1,2,3,-5,-5,3,2,1}, {0,2,4,6,8,8,6,4,2}, {0,3,6,9,12,12,9,6,3}, {0,4,8,12,16,16,12,8,4}, {0,20,20,20,20,20,20,20,20}, {0,90,90,90,90,90,90,90,90} }; printf("Initializing Strategy. \n"); for (y = 0; y < 9 ; y++) { for (x=0; x < 9; x++) { // Set up knight, bishop, rook, and queen board values positionValue [1] [x] [y] = corePiecePosition [y] [x]; positionValue [2] [x] [y] = corePiecePosition [y] [x]; positionValue [3] [x] [y] = corePiecePosition [y] [x]; positionValue [4] [x] [y] = corePiecePosition [y] [x]; // Set up king board values positionValue [5] [x] [y] = kingPiecePosition [y] [x]; // Set up pawn board values positionValue [6] [x] [y] = pawnPiecePosition [y] [x]; } } } // This routine sets up the chess pieces at the start of a game. void initializeBoard(void) { int x, y; canCastle = 1; printf("Initializing Board. \n"); for (x = 0; x < 9 ; x++) for (y=0; y < 9; y++) board [ply] [x] [y] = 0; board [ply] [1][1] = 3; board [ply] [2][1] = 1; board [ply] [3][1] = 2; board [ply] [4][1] = 4; board [ply] [5][1] = 5; board [ply] [6][1] = 2; board [ply] [7][1] = 1; board [ply] [8][1] = 3; for (x=1; x < 9; x++) { board [ply][x][8] = board [ply][x][1] * -1; board [ply][x] [2] = 6; board [ply] [x] [7] = -6; } } // This routine prints the current chess board. void printBoard() { int x,y; printf("\n a b c d e f g h \n\n"); for (y = 8; y > 0; y--) { printf(" %d", y); for (x=1; x < 9; x++) printf(" %c",pieceLetter [ 7 + board [ply][x][y] ] ); printf("\n\n"); } } int parseMove(char *s) { int x = 0; int valid = 0; int tempPieceTaken, tempMaxPly, tempVerbose; // Make sure inputs are within range. if (s[0] < 'a' || s[0] > 'h' || s[1] < '0' || s[1] > '8' ) valid = -1; if (s[2] < 'a' || s[2] > 'h' || s[3] < '0' || s[3] > '8' ) valid = -1; if (valid == 0 ) { validx1 = s[0] - 'a' + 1; validy1 = s[1] - '0'; validx2 = s[2] - 'a' + 1; validy2 = s[3] - '0'; //The next set of commands validates if a user piece move is valid for all moves except castling and En Passant. // Prepare variables to call the findcomputermove function to see if our move is in generated list of moves. alphabeta[1] = pruningRange * -1; flipBoard(); validMove = 0; ply = 0; tempMaxPly = maxPly; tempVerbose = verbose; maxPly = 1; verbose = 0; findComputerMove(); // Restore settings now that we have checked out the moves maxPly = tempMaxPly; verbose = tempVerbose; flipBoard(); ply = 0; //Handle En Passant //Are we moving a pawn from fifth to the sixth row, diagonally, to a blank spot if (validy1 == 5 && validy2 == 6 && abs (validx2-validx1) == 1 && moveHistory [moveCount] [5] == 0 ) validMove = 1; //Handle castling to the right if (board [ply] [validx1][validy1] == 5 && validx1 == 5 && validy1 == 1 && validx2 == 7 && validy2 == 1 && board [ply] [6][1] == 0 && board [ply] [7][1] == 0 && board [ply] [8][1] == 3 && canCastle == 1 ) validMove = 1; //Handle castling to the left if (board [ply] [validx1][validy1] == 5 && validx1 == 5 && validy1 == 1 && validx2 == 3 && validy2 == 1 && board [ply] [4][1] == 0 && board [ply] [3][1] == 0 && board [ply] [2][1] == 0 && board [ply] [1][1] == 3 && canCastle == 1 ) validMove = 1; //If this isn't a valid move then set valid to a return value of -1. if (validMove == 0 && enforceValidMoves == 1) valid = -1; //Set up board, then undo changes, to see if this would put the King in Check tempPieceTaken = board [ply] [validx2][validy2] ; board [ply] [validx2][validy2] = board [ply] [validx1][validy1]; board [ply] [validx1][validy1] = 0; if (whiteInCheck() == 1 && enforceValidMoves == 1) { printf("\nThis move puts you in Check!\n"); valid = -1; } board [ply] [validx1][validy1] = board [ply] [validx2][validy2]; board [ply] [validx2][validy2] = tempPieceTaken; } return valid; } int whiteInCheck() { int tempVerbose, tempMaxPly; int check = 0; // Prepare variables to call the findcomputermove function to see if the white king can be attacked. alphabeta[1] = pruningRange * -1; alphabeta[2] = pruningRange; ply = 0; tempMaxPly = maxPly; tempVerbose = verbose; maxPly = 2; verbose = 0; findComputerMove(); // Restore settings now that we have checked out the moves maxPly = tempMaxPly; verbose = tempVerbose; // If the piece destination is a King then White is in check. if ( board[0][besttox][besttoy] == 5 ) check = 1; return check; } void movePiece(char *s) { int x1,x2,y1,y2; x1 = s[0] - 'a' + 1; y1 = s[1] - '0'; x2 = s[2] - 'a' + 1; y2 = s[3] - '0'; moveCount = moveCount + 1; if (moveCount == 395) { printf("\nMove history limit reached as we approach 400 moves."); printf("\nYou can continue playing, but move history is being reset.\n"); moveCount = 1; } //Store piece taken if any. moveHistory [moveCount] [5] = board [ply] [x2][y2] ; //Update the board with the move. board [ply] [x2][y2] = board [ply] [x1][y1]; board [ply] [x1][y1] = 0; //Promote pawn to queen if (board [ply] [x2] [y2] == 6 && y2 == 8) { printf("\nPromoting White pawn to queen.\n"); board [ply] [x2] [y2] = 4; } //Handle En Passant //Are we moving a pawn from fifth to the sixth row, diagonally, to a blank spot if (y1 == 5 && y2 == 6 && abs (x2-x1) == 1 && moveHistory [moveCount] [5] == 0 ) { printf("\nRecognizing En passant.\n"); board [ply][x2][y1] = 0; } //Handle castling to the right if (board [ply] [x2][y2] == 5 && x2 == 7 && y2 == 1 && x1 == 5 && y2 == 1 && canCastle == 1 ) { printf("\nCastling King.\n"); board [ply][6][1] = board[ply][8][1]; board[ply][8][1] = 0; } //Handle castling to the left if (board [ply] [x2][y2] == 5 && x2 == 3 && y2 == 1 && x1 == 5 && y2 == 1 && canCastle == 1 ) { printf("\nCastling King.\n"); board [ply][4][1] = board[ply][1][1]; board[ply][1][1] = 0; } // Once the king is moved, you can no longer castle. if ( board [ply] [x2][y2] == 5 ) canCastle = 0; // Save move history moveHistory [moveCount] [0] = x1; moveHistory [moveCount] [1] = y1; moveHistory [moveCount] [2] = x2; moveHistory [moveCount] [3] = y2; moveHistory [moveCount] [4] = board [ply] [x2] [y2] ; } int findComputerMove() { int x,y; //Enter the next ply down. ply = ply + 1; // Set up evaluation board. copyEvalBoard(); for (y = 1; y < 9; y++) { for (x = 1; x < 9; x++) { if (board [ply][x][y] == -1 && pruneIt == 0) checkOutKnight(x,y); if (board [ply][x][y] == -3 && pruneIt == 0 ) checkOutRook(x,y); if (board [ply][x][y] == -2 && pruneIt == 0 ) checkOutBishop(x,y); if (board [ply][x][y] == -6 && pruneIt == 0 ) checkOutPawn(x,y); if ( (board [ply][x][y] == -4 || board [ply][x][y] == -5) && pruneIt == 0 ) { //If its a queen or king treat it like a combo of rook and bishop. //The functions below will limit travel to one square if its the king. checkOutBishop(x,y); checkOutRook(x,y); } //If we have reached an alpha beta cut off then exit the evaluation loop for this ply. if (pruneIt == 1) { x = 9; y = 9; pruneIt = 0; } } } ply = ply - 1; } examineMove (int x, int y, int dx, int dy) { nodesSearched = nodesSearched + 1; if (verbose > ply) { printf("\n"); for (counter = 1; counter <= ply; counter++) printf(" "); if (ply%2 == 1) { printf("Ply %d black %s %c%d",ply,pieceName[ abs ( board [ply] [x] [y] ) ], columnLetter[x],y); printf(":%c%d-%c%d",columnLetter[x], y, columnLetter[dx],dy); } else { printf("Ply %d white %s %c%d",ply,pieceName[ abs ( board [ply] [x] [y] ) ], columnLetter[x],9-y); printf(":%c%d-%c%d",columnLetter[x], 9-y, columnLetter[dx],9-dy); } } //store the proposed move. if (ply == 1) { fromx = x; fromy = y; tox = dx; toy = dy; //This conditional is used to help parse if a user entered move is valid. if (validx1 == x && validx2 == dx && validy1 == 9-y && validy2 == 9-dy) validMove = 1; } //Set up proposed move to calculate score. copyEvalBoard(); board [ply] [dx] [dy] = board [ply] [x] [y] ; //If pawn reaches the 8th file then promote to queen. if (board [ply] [dx] [dy] == -6 && dy == 1) board [ply] [dx] [dy] = -4; board [ply] [x] [y] = 0; if (ply < maxPly) findComputerMove(); if (ply == maxPly) evalScore = calcBoardValue(); //reset the board for next evaluation copyEvalBoard(); if (ply > 1 && ply % 2 == 1) // Manage odd plys { if (ply == maxPly && evalScore > alphabeta[ply] ) alphabeta[ply] = evalScore; if (maxPly > ply && alphabeta[ply+1] > alphabeta[ply] ) alphabeta[ply] = alphabeta [ply +1]; // apply pruning if (applyPruning == 1 && (alphabeta[ply] + aspirationWindow ) > alphabeta[ply-1] ) { pruneIt = 1; nodesPruned[ply-1] = nodesPruned[ply-1] + 1; } alphabeta[ply+1] = pruningRange; } if (ply > 1 && ply % 2 == 0) //Manage even plys { //Flip the score as we are in an even ply layer. evalScore = evalScore * -1; if (ply == maxPly && evalScore < alphabeta[ply] ) alphabeta[ply] = evalScore; if (maxPly > ply && alphabeta[ply+1] < alphabeta[ply] ) alphabeta [ply] = alphabeta [ply + 1]; //apply pruning if (applyPruning == 1 && alphabeta[ply] < ( alphabeta [ply-1] + aspirationWindow ) ) { pruneIt = 1; nodesPruned[ply-1] = nodesPruned[ply-1] + 1; } alphabeta[ply+1] = pruningRange * -1; } if (ply == 1) { if (maxPly == 1 && evalScore > alphabeta[ply] ) { alphabeta[ply] = evalScore; bestfromx = fromx; bestfromy = fromy; besttox = tox; besttoy = toy; if (verbose > ply) printf(" New alpha score. %d", alphabeta[ply]); } if (alphabeta[ply + 1] > alphabeta[ply] && maxPly > 1) { alphabeta[ply] = alphabeta[ply + 1]; bestfromx = fromx; bestfromy = fromy; besttox = tox; besttoy = toy; if (verbose > ply) printf(" New alpha score: %d ", alphabeta[ply] ); } alphabeta[ply + 1] = pruningRange; } } int makeComputerMove () { int x; //Analysis is complete, return results. //Save piece taken, if any moveCount = moveCount + 1; moveHistory [moveCount] [5] = board [0][besttox][besttoy] ; printf("\n\nSearched %d nodes.", (int) nodesSearched); for (x = 1; x < maxPly; x++) printf("\nNodes pruned at Ply %d: %d", x, (int) nodesPruned[x] ); printf ("\n\nMoving %s %c%d to %c%d ", pieceName[ abs( board[0][bestfromx][bestfromy] ) ] , columnLetter[bestfromx],bestfromy,columnLetter[besttox],besttoy); if (board [0][besttox][besttoy] > 0) printf("and taking %s.", pieceName[ board[0][besttox][besttoy] ] ); if (board [0][besttox][besttoy] == 5) { printf("\n\nCheckmate!\n\n"); printf("\n\nThank you for the game.\n\n"); } board [0][besttox][besttoy] = board [0][bestfromx][bestfromy]; board [0][bestfromx][bestfromy] = 0; if ( board [0][besttox][besttoy] == -6 && besttoy == 1) { printf("Promoting Pawn to Queen.\n"); board [0][besttox][besttoy] = -4; } printf("\n"); // Save move history moveHistory [moveCount] [0] = bestfromx; moveHistory [moveCount] [1] = bestfromy; moveHistory [moveCount] [2] = besttox; moveHistory [moveCount] [3] = besttoy; moveHistory [moveCount] [4] = board [0][besttox][besttoy] ; } int checkOutBishop(int x, int y) { int travel, dx, dy; // Bishop travel Northwest first. dx=x-1; dy=y+1; travel = 1; while (dx > 0 && dx < 9 && dy > 0 && dy < 9 && travel == 1) { // If we landed on a friendly stop travel. if (board [ply] [dx] [dy] < 0) travel = 0; else { // If we landed on an opponent or its the king, set travel to zero to limit reach. if (board [ply] [dx] [dy] > 0 || board [ply] [x] [y] == -5) travel = 0; examineMove (x, y, dx, dy); } dy=dy+1; dx=dx-1; } // Bishop travel Northeast second. dx=x+1; dy=y+1; travel = 1; while (dx > 0 && dx < 9 && dy > 0 && dy < 9 && travel == 1) { // If we landed on a friendly piece stop travel. if (board [ply] [dx] [dy] < 0) travel = 0; else { // If we landed on an opponent or its the king, set travel to zero to limit reach. if (board [ply] [dx] [dy] > 0 || board [ply] [x] [y] == -5) travel = 0; examineMove (x, y, dx, dy); } dy=dy+1; dx=dx+1; } // Bishop travel Southeast third dx=x+1; dy=y-1; travel = 1; while (dx > 0 && dx < 9 && dy > 0 && dy < 9 && travel == 1) { // If we landed on a friendly piece stop travel. if (board [ply] [dx] [dy] < 0) travel = 0; else { // If we landed on an opponent or its the king, set travel to zero to limit reach. if (board [ply] [dx] [dy] > 0 || board [ply] [x] [y] == -5) travel = 0; examineMove (x, y, dx, dy); } dx=dx+1; dy=dy-1; } // Bishop travel Southwest. dx=x-1; dy=y-1; travel = 1; while (dx > 0 && dx < 9 && dy > 0 && dy < 9 && travel == 1) { // If we landed on a friendly piece stop travel. if (board [ply] [dx] [dy] < 0 ) travel = 0; else { // If we landed on an opponent or its the king, set travel to zero to limit reach. if (board [ply] [dx] [dy] > 0 || board [ply] [x] [y] == -5) travel = 0; examineMove (x, y, dx, dy); } dx=dx-1; dy=dy-1; } } int checkOutRook(int x, int y) { int travel, dx, dy; // Travel North first. dx=x; dy=y+1; travel = 1; while (dx > 0 && dx < 9 && dy > 0 && dy < 9 && travel == 1) { // If we landed on a friendly piece stop travel. if (board [ply] [dx] [dy] < 0 ) travel = 0; else { // If we landed on an opponent or its the king, set travel to zero to limit reach. if (board [ply] [dx] [dy] > 0 || board [ply] [x] [y] == -5) travel = 0; examineMove (x, y, dx, dy); } dy=dy+1; } // Travel South second. dx=x; dy=y-1; travel = 1; while (dx > 0 && dx < 9 && dy > 0 && dy < 9 && travel == 1) { // If we landed on a friendly piece stop travel. if (board [ply] [dx] [dy] < 0 ) travel = 0; else { // If we landed on an opponent or its the king, set travel to zero to limit reach. if (board [ply] [dx] [dy] > 0 || board [ply] [x] [y] == -5) travel = 0; examineMove (x, y, dx, dy); } dy=dy-1; } // Rook travel left third dx=x-1; dy=y; travel = 1; while (dx > 0 && dx < 9 && dy > 0 && dy < 9 && travel == 1) { // If we landed on a friendly piece stop travel. if (board [ply] [dx] [dy] < 0 ) travel = 0; else { // If we landed on an opponent or its the king, set travel to zero to limit reach. if (board [ply] [dx] [dy] > 0 || board [ply] [x] [y] == -5) travel = 0; examineMove (x, y, dx, dy); } dx=dx-1; } // Rook travel right finally. dx=x+1; dy=y; travel = 1; while (dx > 0 && dx < 9 && dy > 0 && dy < 9 && travel == 1) { // If we landed on a friendly piece stop travel. if (board [ply] [dx] [dy] < 0) travel = 0; else { // If we landed on an opponent or its the king, set travel to zero to limit reach. if (board [ply] [dx] [dy] > 0 || board [ply] [x] [y] == -5) travel = 0; examineMove (x, y, dx, dy); } dx=dx+1; } } int checkOutKnight(int x, int y) { int z, dx, dy; for (z = 1; z < 9; z++) { switch (z) { case 1: { dx = x -1; dy = y -2; break; } case 2: { dx = x +1; dy = y -2; break; } case 3: { dx = x-2; dy = y+1; break; } case 4: { dx = x-2; dy = y-1; break; } case 5: { dx = x+2; dy = y+1; break; } case 6: { dx = x+2; dy = y-1; break; } case 7: { dx = x-1; dy = y+2; break; } case 8: { dx = x+1; dy = y+2; break; } } if (dx <9 && dx>0 && dy<9 && dy>0 && board [ply] [dx] [dy] > -1) examineMove (x, y, dx, dy); } } int checkOutPawn(int x, int y) { int dx, dy; // Pawn advances to rows forward. dx=x; dy = y-2; if (y == 7 && board [ply][x][y-1] == 0 && board [ply][x][y-2] == 0 ) examineMove (x, y, dx, dy); // Move pawn one file. dx=x; dy = y-1; if (y > 1 && board [ply][x][y-1] == 0 ) examineMove (x, y, dx, dy); // Pawn takes piece to the left dx = x-1; dy = y-1; if (y > 1 && x > 1 && board [ply][x-1][y-1] > 0 ) examineMove (x, y, dx, dy); // Pawn takes piece to the right. dx = x+1; dy = y-1; if (y > 1 && x < 8 && board [ply][x+1][y-1] > 0 ) examineMove (x, y, dx, dy); } int copyEvalBoard(void) { int x,y; // If its ply one just duplicate the board otherwise flip the board from one ply to the next. if (ply == 1) { for (x = 1; x < 9; x++) for (y = 1; y < 9; y++) board [ply][x][y] = board [ply-1][x][y]; } else { for (x = 1; x < 9; x++) for (y = 1; y < 9; y++) board [ply][x][y] = board [ply-1][x][9-y] * -1 ; } } int flipBoard(void) { int x,y; // This routine flips the board and is used to help parse use moves. for (x = 1; x < 9; x++) for (y = 1; y < 9; y++) board [1][x][y] = board [0][x][y]; for (x = 1; x < 9; x++) for (y = 1; y < 9; y++) board [0][x][y] = board [1][x][9-y] * -1 ; } void showMoveHistory() { int x; printf("\nMove History\n"); for (x = 1; x <= moveCount; x++) { printf("\n%d: ",x); printf ("Moved %s %c%d to %c%d ", pieceName[ abs( moveHistory[x][4] ) ] , columnLetter[ moveHistory[x][0] ],moveHistory[x][1],columnLetter[ moveHistory[x][2] ],moveHistory [x][3]); if (moveHistory[x][5] != 0) printf("and taking %s.", pieceName[ abs ( moveHistory[x][5] ) ] ); } printf("\n"); } void newGame() { printf("\nWelcome to John Miranda's Chess Game.\n"); printf("Enter quit to exit or help for assistance\n\n"); initializeBoard(); initializeStrategy(); moveCount = 0; } int main() { char yourMove[10]; int score = 0; int command = 0; int x = 0; int tempPieceTaken, tempMaxPly, tempVerbose; newGame(); while (gameIsOn == 1) { score = calcBoardValue() ; printf("\nYour Score: %d \n", (score - randomValue) * -1); printBoard(); command = 0; printf("\nEnter your move (eg: d2d4): "); scanf("%s", yourMove); if (!strcmp(yourMove, "quit") || !strcmp(yourMove, "q") || !strcmp(yourMove, "bye") ) { printf("\nThank you for the game.\n\n"); gameIsOn = 0; break; } if (!strcmp(yourMove, "new") || !strcmp(yourMove, "n") ) { command = 1; newGame(); } if (!strcmp(yourMove, "moves") ) { command = 1; showMoveHistory(); } if (!strcmp(yourMove, "maxply1") || !strcmp(yourMove, "m1") ) { command = 1; maxPly = 1; printf("\nMaximum search ply set to 1.\n\n"); } if (!strcmp(yourMove, "maxply2") || !strcmp(yourMove, "m2") ) { command = 1; maxPly = 2; printf("\nMaximum search ply set to 2.\n\n"); } if (!strcmp(yourMove, "maxply3") || !strcmp(yourMove, "m3") ) { command = 1; maxPly = 3; printf("\nMaximum search ply set to 3.\n\n"); } if (!strcmp(yourMove, "maxply4") || !strcmp(yourMove, "m4") ) { command = 1; maxPly = 4; printf("\nMaximum search ply set to 4.\n\n"); } if (!strcmp(yourMove, "maxply5") || !strcmp(yourMove, "m5") ) { command = 1; maxPly = 5; printf("\nMaximum search ply set to 5.\n\n"); } if (!strcmp(yourMove, "maxply6") || !strcmp(yourMove, "m6") ) { command = 1; maxPly = 6; printf("\nMaximum search ply set to 6.\n\n"); } if (!strcmp(yourMove, "maxply7") || !strcmp(yourMove, "m7") ) { command = 1; maxPly = 7; printf("\nMaximum search ply set to 7.\n\n"); } if (!strcmp(yourMove, "verbose0") || !strcmp(yourMove, "v0") ) { command = 1; verbose = 0; printf("\nSkipping search messages.\n\n"); } if (!strcmp(yourMove, "verbose1") || !strcmp(yourMove, "v1") ) { command = 1; verbose = 2; printf("\nVerbose to ply 1 set.\n\n"); } if (!strcmp(yourMove, "verbose2") || !strcmp(yourMove, "v2") ) { command = 1; verbose = 3; printf("\nVerbose to ply 2 set.\n\n"); } if (!strcmp(yourMove, "verbose3") || !strcmp(yourMove, "v3") ) { command = 1; verbose = 4; printf("\nVerbose to ply 3 set.\n\n"); } if (!strcmp(yourMove, "pruning") ) { command = 1; applyPruning = 1; printf("\nAlpha Beta pruning enabled.\n\n"); } if (!strcmp(yourMove, "nopruning") ) { command = 1; applyPruning = 0; printf("\nAlpha Beta cutoff pruning disabled.\n\n"); } if (!strcmp(yourMove, "random") ) { command = 1; applyRandom = 1; printf("\nRandom factoring enabled.\n\n"); } if (!strcmp(yourMove, "norandom") ) { command = 1; applyRandom = 0; printf("\nRandom factoring disabled.\n\n"); } if (!strcmp(yourMove, "valid") ) { command = 1; enforceValidMoves = 1; printf("\nEnforcing piece movement.\n\n"); } if (!strcmp(yourMove, "novalid") ) { command = 1; enforceValidMoves = 0; printf("\nDisabling piece movement validation.\n\n"); } if (!strcmp(yourMove, "help") ) { printf("\nHelp:\n\n"); printf(" maxplyn or 'mn' - Sets max search ply to value n [1-7].\n"); printf(" verbosen or 'vn' - Prints search data through ply n [0-3] .\n"); printf(" pruning - Enables Alpha-Beta cutoff pruning.\n"); printf(" nopruning - Disables Alpha-Beta cutoff pruning.\n"); printf(" random - Enables randomization factor.\n"); printf(" norandom - Disables random factor and makes play deterministic.\n"); printf(" moves - Displays move history.\n"); printf(" valid - Enforces piece movement.\n"); printf(" novalid - Allows moving a piece pretty much anywhere.\n"); printf(" new or 'n' - New game.\n"); printf(" quit or bye - Exits game.\n"); printf(" d2d4 - Moves piece from d2 to d4.\n\n"); command = 1; } if (command == 0) { // No command was recognized, lets assume this is a valid move. if (parseMove(yourMove) == -1) printf("\nIllegal Move.\n"); else { // make the move starttime = time(NULL); ply = 0; pruneIt = 0; nodesSearched =0; //Set up initial alpha beta cut off values. alphabeta[0] = pruningRange; for (x = 1; x <= maxPly; x++) { alphabeta [x] = alphabeta [x-1] * -1; nodesPruned [x] = 0; } movePiece(yourMove); printBoard(); findComputerMove(); makeComputerMove(); ply = 0; endtime = time(NULL); printf("\nTime elapsed: %d seconds", (int) (endtime - starttime ) ); if (endtime > starttime) printf("\nNodes per second: %d\n", (int) ( nodesSearched / (endtime - starttime) ) ); if (whiteInCheck() == 1) { printf("\nYou are in check!\n"); canCastle = 0; //The next set of code does a 2 ply search to see if this is checkmate. alphabeta[1] = pruningRange * -1; alphabeta[2] = pruningRange; flipBoard(); validMove = 0; ply = 0; tempMaxPly = maxPly; tempVerbose = verbose; maxPly = 2; verbose = 0; findComputerMove(); // Restore settings now that we have checked out the moves maxPly = tempMaxPly; verbose = tempVerbose; flipBoard(); ply = 0; if ( alphabeta[1] < -6000 ) printf("\n Checkmate!\n" ); } } } } return (0); }