#include "chess.h" int isvalid_move(int side, int start_row, int start_col, int end_row, int end_col); int ischeck(int side, int row, int col); int ischeck_mate(int side, int row, int col); void find_kings(); extern int board[ROW_SIZE][ROW_SIZE]; extern int check, white_king_row, white_king_col, black_king_row, black_king_col; /* Returns 1 if king is in check, returns 0 otherwise */ int ischeck(int side, int row, int col) { /* Check horizontal */ /* Check left */ for (int i = row - 1; i >= 0; i--) { int piece = board[i][col]; if (piece > 0) { /* If the square is not empty */ if ((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) { /* If the piece belongs to the opponent */ if (piece % 10 == 5 || piece % 10 == 2) { /* If the piece is a rook or queen then the king is in check*/ return 1; } else { /* If its another piece, stop looking left as the king is screened by the non rook or queen piece */ break; } } else { /* If it is a friendly piece, the king is safe to the left so stop looking*/ break; } } } /* Check right */ for (int i = row + 1; i < ROW_SIZE; i++) { int piece = board[i][col]; if (piece > 0) { /* If the square is not empty */ if ((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) { /* If the piece belongs to the opponent */ if (piece % 10 == 5 || piece % 10 == 2) { /* If the piece is a rook or queen then the king is in check*/ return 1; } else { /* If its another piece, stop looking left as the king is screened by the non rook or queen piece */ break; } } else { /* If it is a friendly piece, the king is safe to the left so stop looking*/ break; } } } /* Check vertical */ /* Check down */ for (int i = col - 1; i >= 0; i--) { int piece = board[row][i]; if (piece > 0) { /* If the square is not empty */ if ((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) { /* If the piece belongs to the opponent */ if (piece % 10 == 5 || piece % 10 == 2) { /* If the piece is a rook or queen then the king is in check*/ return 1; } else { /* If its another piece, stop looking left as the king is screened by the non rook or queen piece */ break; } } else { /* If it is a friendly piece, the king is safe to the left so stop looking*/ break; } } } /* Check up */ for (int i = col + 1; i < ROW_SIZE; i++) { int piece = board[row][i]; if (piece > 0) { /* If the square is not empty */ if ((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) { /* If the piece belongs to the opponent */ if (piece % 10 == 5 || piece % 10 == 2) { /* If the piece is a rook or queen then the king is in check*/ return 1; } else { /* If its another piece, stop looking left as the king is screened by the non rook or queen piece */ break; } } else { /* If it is a friendly piece, the king is safe to the left so stop looking*/ break; } } } /* Check diagonal */ /* Check up and left */ for (int i = row + 1, j = col - 1; i < ROW_SIZE && j >= 0; i++, j--) { int piece = board[i][j]; if (piece > 0) { /* If the square is not empty */ if ((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) { /* If the piece belongs to the opponent */ if (piece % 10 == 5 || piece % 10 == 4) { /* If the piece is a queen or bishop */ return 1; } else if (piece == BLACK_PAWN && side == WHITE) { return 1; } else { /* If its another piece, stop looking left as the king is screened by the non rook or queen piece */ break; } } else { /* If it is a friendly piece, the king is safe to the left so stop looking*/ break; } } } /* Check up and right */ for (int i = row + 1, j = col + 1; i < ROW_SIZE && j < ROW_SIZE; i++, j++) { int piece = board[i][j]; if (piece > 0) { /* If the square is not empty */ if ((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) { /* If the piece belongs to the opponent */ if (piece % 10 == 5 || piece % 10 == 4) { /* If the piece is a bishop */ return 1; } else if (piece == BLACK_PAWN && side == WHITE) { return 1; } else { /* If its another piece, stop looking left as the king is screened by the non rook or queen piece */ break; } } else { /* If it is a friendly piece, the king is safe to the left so stop looking*/ break; } } } /* Check down and left */ for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { int piece = board[i][j]; if (piece > 0) { /* If the square is not empty */ if ((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) { /* If the piece belongs to the opponent */ if (piece % 10 == 5 || piece % 10 == 4) { /* If the piece is a bishop */ return 1; } else if (piece == WHITE_PAWN && side == BLACK) { return 1; } else { /* If its another piece, stop looking left as the king is screened by the non rook or queen piece */ break; } } else { /* If it is a friendly piece, the king is safe to the left so stop looking*/ break; } } } /* Check down and right */ for (int i = row - 1, j = col + 1; i >=0 && j < ROW_SIZE; i--, j++) { int piece = board[i][j]; if (piece > 0) { /* If the square is not empty */ if ((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) { /* If the piece belongs to the opponent */ if (piece % 10 == 5 || piece % 10 == 4) { /* If the piece is a bishop */ return 1; } else if (piece == WHITE_PAWN && side == BLACK) { /* If white pawn is below and to right if a king, that is check */ return 1; } else { /* If its another piece, stop looking left as the king is screened by the non rook or queen piece */ break; } } else { /* If it is a friendly piece, the king is safe to the left so stop looking*/ break; } } } /* Check for knights */ if (board[row-2][col-1] > 0){ if (row-2 >= 0 && row-2 < ROW_SIZE && col-1 >=0 && col-1 < ROW_SIZE) { /* Only check if the resulting row and column are valid values on the board */ int piece = board[row-2][col-1]; if (((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) && piece % 10 == 3) { /* If it is an opponent's knight */ return 1; } } } if (board[row-2][col+1] > 0) { if (row-2 >= 0 && row-2 < ROW_SIZE && col+1 >=0 && col+1 < ROW_SIZE) { int piece = board[row-2][col+1]; if (((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) && piece % 10 == 3) { /* If it is an opponent's knight */ return 1; } } } if (board[row-1][col-2] > 0) { if (row-1 >= 0 && row-1 < ROW_SIZE && col-2 >=0 && col-2 < ROW_SIZE) { int piece = board[row-1][col-2]; if (((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) && piece % 10 == 3) { /* If it is an opponent's knight */ return 1; } } } if (board[row-1][col+2] > 0){ if (row-1 >= 0 && row-1 < ROW_SIZE && col+2 >=0 && col+2 < ROW_SIZE) { int piece = board[row-1][col+2]; if (((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) && piece % 10 == 3) { /* If it is an opponent's knight */ return 1; } } } if (board[row+2][col-1] > 0) { if (row+2 >= 0 && row+2 < ROW_SIZE && col-1 >=0 && col-1 < ROW_SIZE) { int piece = board[row+2][col-1]; if (((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) && piece % 10 == 3) { /* If it is an opponent's knight */ return 1; } } else { } } if (board[row+2][col+1] > 0) { if (row+2 >= 0 && row+2 < ROW_SIZE && col+1 >=0 && col+1 < ROW_SIZE) { int piece = board[row+2][col+1]; if (((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) && piece % 10 == 3) { /* If it is an opponent's knight */ return 1; } } } if (board[row+1][col-2] > 0) { if (row+1 >= 0 && row+1 < ROW_SIZE && col-2 >=0 && col-2 < ROW_SIZE) { int piece = board[row+1][col-2]; if (((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) && piece % 10 == 3) { /* If it is an opponent's knight */ return 1; } } } if (board[row+1][col+2] > 0) { if (row+1 >= 0 && row+1 < ROW_SIZE && col+2 >=0 && col+2 < ROW_SIZE) { int piece = board[row+1][col+2]; if (((side == WHITE && piece > 10) || (side == BLACK && piece < 10)) && piece % 10 == 3) { /* If it is an opponent's knight */ return 1; } } } return 0; } int can_king_move(int side, int row, int col); int can_piece_block(int side, int row, int col); /* Returns 1 if checkmate, 0 if not */ int ischeck_mate(int side, int row, int col) { if(!can_king_move(side, row, col)) { if(!can_piece_block(side, row, col)) { return 1; } } return 0; } int can_piece_block(int side, int row, int col) { /* Brute force check if any move causes the king not to be in check */ for (int i = 0; i < ROW_SIZE; i++) { for (int j = 0; j < ROW_SIZE; j++) { if ((board[i][j] < 10 && side == WHITE) || (board[i][j] > 10 && side == BLACK)) { int piece = board[i][j]; for (int k = 0; k < ROW_SIZE; k++){ for(int l = 0; l < ROW_SIZE; l++) { if (isvalid_move(side, i, j, k, l)) { /* Make the move and run ischeck to see if the king is still in check afterwards */ int destination_piece = board[k][l]; board[k][l] = piece; board[i][j] = 0; find_kings(); /* Find the kings in case they have moved */ /* If the king is not in check after this move, then a valid move exists, so no checkmate*/ if (side == WHITE) { if(!ischeck(WHITE, white_king_row, white_king_col)) { /* Make sure to undo the test move */ board[i][j] = piece; board[k][l] = destination_piece; find_kings(); return 1; } } else if (side == BLACK) { if (!ischeck(BLACK, black_king_row, black_king_col)) { /* Make sure to undo the test move */ board[i][j] = piece; board[k][l] = destination_piece; find_kings(); //printw("%d %d -> %d %d gets the black king out of check", i, j, k, l); return 1; } } /* Make sure to undo the test move */ board[i][j] = piece; board[k][l] = destination_piece; } } } } } } return 0; } /* Returns 0 if the King can safely move to a square to get out of check */ int can_king_move(int side, int row, int col) { if (!ischeck(side, row, col)) { /* If the king is not in check in the current position, checkmate is not possible */ return 1; } /* Check if the king can move safely move to any square around him*/ int temp_row, temp_col; /* row+1, col */ temp_row = row + 1; temp_col = col; if (isvalid_move(side, row, col, temp_row, temp_col) && !ischeck(side, temp_row, temp_col) && temp_row >=0 && temp_row < ROW_SIZE && temp_col >=0 && temp_col < ROW_SIZE) { return 1; } /* row+1, col+1 */ temp_row = row + 1; temp_col = col + 1; if (isvalid_move(side, row, col, temp_row, temp_col) && !ischeck(side, temp_row, temp_col) && temp_row >=0 && temp_row < ROW_SIZE && temp_col >=0 && temp_col < ROW_SIZE) { return 1; } /* row, col+1 */ temp_row = row; temp_col = col + 1; if (isvalid_move(side, row, col, temp_row, temp_col) && !ischeck(side, temp_row, temp_col) && temp_row >=0 && temp_row < ROW_SIZE && temp_col >=0 && temp_col < ROW_SIZE) { return 1; } /* row-1, col-1 */ temp_row = row - 1; temp_col = col - 1; if (isvalid_move(side, row, col, temp_row, temp_col) && !ischeck(side, temp_row, temp_col) && temp_row >=0 && temp_row < ROW_SIZE && temp_col >=0 && temp_col < ROW_SIZE) { return 1; } /* row-1, col */ temp_row = row - 1; temp_col = col; if (isvalid_move(side, row, col, temp_row, temp_col) && !ischeck(side, temp_row, temp_col) && temp_row >=0 && temp_row < ROW_SIZE && temp_col >=0 && temp_col < ROW_SIZE) { return 1; } /* row-1, col+1 */ temp_row = row - 1; temp_col = col + 1; if (isvalid_move(side, row, col, temp_row, temp_col) && !ischeck(side, temp_row, temp_col) && temp_row >=0 && temp_row < ROW_SIZE && temp_col >=0 && temp_col < ROW_SIZE) { return 1; } /* row, col-1 */ temp_row = row; temp_col = col - 1; if (isvalid_move(side, row, col, temp_row, temp_col) && !ischeck(side, temp_row, temp_col) && temp_row >=0 && temp_row < ROW_SIZE && temp_col >=0 && temp_col < ROW_SIZE) { return 1; } /* row+1, col-1 */ temp_row = row + 1; temp_col = col - 1; if (isvalid_move(side, row, col, temp_row, temp_col) && !ischeck(side, temp_row, temp_col) && temp_row >=0 && temp_row < ROW_SIZE && temp_col >=0 && temp_col < ROW_SIZE ){ return 1; } getch(); return 0; }