summaryrefslogtreecommitdiff
path: root/src/chesshelpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/chesshelpers.c')
-rw-r--r--src/chesshelpers.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/chesshelpers.c b/src/chesshelpers.c
new file mode 100644
index 0000000..b64a0f4
--- /dev/null
+++ b/src/chesshelpers.c
@@ -0,0 +1,154 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "vector.h"
+#include "chesshelpers.h"
+
+board_t init_board(int** pieces) {
+ board_t board;
+ board.pieces = pieces;
+ board.whiteCanCastleKingside = 1;
+ board.whiteCanCastleQueenside = 1;
+ board.blackCanCastleKingside = 1;
+ board.blackCanCastleQueenside = 1;
+ board.lastPawnMove = -1;
+ return board;
+}
+//function applies side effects to board values like king move state
+board_t make_move(board_t board, vector_t origin, vector_t end) {
+ int piece = board.pieces[origin.mx][origin.my];
+ int captured = board.pieces[end.mx][end.my];
+ board.pieces[origin.mx][origin.my] = 0;
+ board.pieces[end.mx][end.my] = piece;
+ //white king moved
+ if(piece == king) {
+ board.whiteCanCastleQueenside = 0;
+ board.whiteCanCastleKingside = 0;
+ //if the king moved farther than it normally could, move must have been castling. move the rook as well
+ if(origin.mx == 4 && end.mx == 6) {
+ board = make_move(board, init_vector(7, 7), init_vector(5, 7));
+ }
+ else if(origin.mx == 4 && end.mx == 2) {
+ board = make_move(board, init_vector(0, 7), init_vector(3, 7));
+ }
+ }
+ //white kingside rook moved
+ else if(origin.mx == 7 && origin.my == 7) {
+ board.whiteCanCastleKingside = 0;
+ }
+ //white queenside rook moved
+ else if(origin.mx == 0 && origin.my == 7) {
+ board.whiteCanCastleQueenside = 0;
+ }
+ //black king moved
+ else if(piece == king + 6) {
+ board.blackCanCastleQueenside = 0;
+ board.blackCanCastleKingside = 0;
+ //if the king moved farther than it normally could, move must have been castling. move the rook as well
+ if(origin.mx == 4 && end.mx == 6) {
+ board = make_move(board, init_vector(7, 0), init_vector(5, 0));
+ }
+ else if(origin.mx == 4 && end.mx == 2) {
+ board = make_move(board, init_vector(0, 0), init_vector(3, 0));
+ }
+ }
+ //black kingside rook moved
+ else if(origin.mx == 7 && origin.my == 0) {
+ board.blackCanCastleKingside = 0;
+ }
+ //black queenside rook moved
+ else if(origin.mx == 0 && origin.my == 0) {
+ board.blackCanCastleQueenside = 0;
+ }
+ //this is not an else if! lastPawnMove must be reset
+ if(piece == pawn || piece == pawn + 6) {
+ board.lastPawnMove = origin.mx;
+ //check if move was an en passant capture
+ if(captured == 0 && origin.mx != end.mx) {
+ //kill the enemy pawn
+ board.pieces[end.mx][origin.my] = 0;
+ }
+ }
+ else {
+ //en passant no longer possible
+ board.lastPawnMove = -1;
+ }
+ return board;
+}
+board_t clone_board(board_t board) {
+ board_t newBoard = board;
+ int** pieces = malloc(8 * sizeof(int*));
+ for(int r = 0; r < 8; r++) {
+ pieces[r] = malloc(8 * sizeof(int));
+ for(int c = 0; c < 8; c++) {
+ pieces[r][c] = board.pieces[r][c];
+ }
+ }
+ newBoard.pieces = pieces;
+ return newBoard;
+}
+int in_board(vector_t position) {
+ return position.mx < 8 && position.mx >= 0 && position.my < 8 && position.my >= 0;
+}
+int is_empty(board_t board, vector_t position) {
+ return board.pieces[position.mx][position.my] == 0;
+}
+int is_color(board_t board, vector_t position, int color) {
+ if(color == 0) {
+ return board.pieces[position.mx][position.my] >= 1 && board.pieces[position.mx][position.my] <= 6;
+ }
+ else {
+ return board.pieces[position.mx][position.my] >= 7;
+ }
+}
+//returns true if a pawn that moved two squares would have been here if it moved one square
+int would_have_been_pawn(board_t board, vector_t position, int color) {
+ if(board.lastPawnMove == position.mx) {
+ if((position.my == 6 && color == 0) || (position.my == 2 && color == 1)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+//converts board coordinates into algebraic notation
+char* get_readable_coords(vector_t position) {
+ char* output = malloc(3 * sizeof(char));
+ output[0] = 'a' + position.mx;
+ output[1] = '8' - position.my;
+ output[2] = '\0';
+ return output;
+}
+//gets the proper algebraic notation for the move
+char* get_move_name(board_t board, vector_t origin, vector_t end) {
+ int piece = board.pieces[origin.mx][origin.my];
+ if(piece > 6) {
+ piece -= 6;
+ }
+ if(piece != 1) {
+ char cPiece = piece == pawn ? 'P' : piece == knight ? 'N' : piece == bishop ? 'B' : piece == rook ? 'R' : piece == queen ? 'Q' : 'K';
+ int isCapture = board.pieces[end.mx][end.my] != 0;
+ char* output = calloc(isCapture ? 5 : 4, sizeof(char));
+ output[0] = cPiece;
+ if(isCapture) {
+ output[1] = 'x';
+ }
+ char* rEnd = get_readable_coords(end);
+ strcat(output, rEnd);
+ free(rEnd);
+ output[isCapture ? 4 : 3] = '\0';
+ return output;
+ }
+ else {
+ int isCapture = board.pieces[end.mx][end.my] != 0;
+ char* output = calloc(isCapture ? 5 : 3, sizeof(char));
+ if(isCapture) {
+ output[0] = 'a' + origin.mx;
+ output[1] = 'x';
+ }
+ char* rEnd = get_readable_coords(end);
+ strcat(output, rEnd);
+ free(rEnd);
+ output[isCapture ? 4 : 2] = '\0';
+ return output;
+ }
+}