From 635486c9b5801fd886150414deaaa04f48639d1e Mon Sep 17 00:00:00 2001 From: "Claudio Maggioni (maggicl)" Date: Mon, 19 Aug 2019 14:47:14 +0200 Subject: [PATCH] assigment1-18: done up to check (no checkmate) --- assignment1-18/chess | Bin 0 -> 21976 bytes assignment1-18/chessboard.c | 341 ++++++++++++++++++++++++++---------- 2 files changed, 247 insertions(+), 94 deletions(-) create mode 100755 assignment1-18/chess diff --git a/assignment1-18/chess b/assignment1-18/chess new file mode 100755 index 0000000000000000000000000000000000000000..042241cbb3bb3ce0d00501d2f6772e0e0bad5661 GIT binary patch literal 21976 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 literal 0 HcmV?d00001 diff --git a/assignment1-18/chessboard.c b/assignment1-18/chessboard.c index 661ebc8..2d348e8 100644 --- a/assignment1-18/chessboard.c +++ b/assignment1-18/chessboard.c @@ -1,10 +1,38 @@ // vim: set ts=4 sw=4 et tw=80: #include -#include "./chessboard.h" #include #include #include +#include "./chessboard.h" + +#define DEBUG_BUILD +#ifdef DEBUG_BUILD +#define DEBUG(...) fprintf(stderr, __VA_ARGS__); +#else +#define DEBUG(...) (void) 0; +#endif + +static inline void cb_move(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col); +static inline int sign(int n); +static inline enum player player(struct chessboard* cb, int row, int col); +static inline bool is_empty(struct chessboard* cb, int row, int col); +static bool check_empty_paths(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col); + +static bool can_move_pawn(struct chessboard* cb, enum player p, + int from_row, int from_col, int to_row, int to_col); +static bool can_move_rook(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col); +static bool can_move_knight(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col); +static bool can_move_bishop(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col); +static bool can_move_queen(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col); +static bool can_move_king(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col); void init_chessboard(struct chessboard * cb) { int i; @@ -65,8 +93,8 @@ void print_chessboard(struct chessboard * cb) { } -inline void cb_move(struct chessboard* cb, int from_row, int from_col, int to_row, - int to_col) { +inline void cb_move(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col) { cb->position[to_row][to_col] = cb->position[from_row][from_col]; cb->position[from_row][from_col] = EMPTY; } @@ -76,125 +104,215 @@ inline bool is_empty(struct chessboard* cb, int row, int col) { } inline enum player player(struct chessboard* cb, int row, int col) { - return cb->position[row][col] < 7 ? WHITE : BLACK; + return cb->position[row][col] < 7 ? WHITE : BLACK; } - inline int sign(int n) { return n == 0 ? 0 : (n > 0 ? 1 : -1); } -enum mstatus move_pawn(struct chessboard* cb, enum player p, int from_row, - int from_col, int to_row, int to_col) { +bool can_move_pawn(struct chessboard* cb, enum player p, + int from_row, int from_col, int to_row, int to_col) { + DEBUG("can_move_pawn: from: row %d col %d to: row %d col %d\n", + from_row, from_col, to_row, to_col); + // two forward if in the starting position, no capture is valid if (((p == WHITE && from_row == 1 && to_row == 3 && - is_empty(cb, 2, from_col)) || - (p == BLACK && from_row == 7 && to_row == 5 && - is_empty(cb, 6, from_col))) && - from_col == to_col && - is_empty(cb, to_row, to_col)) { - cb_move(cb, from_row, from_col, to_row, to_col); - return VALID; - // one forward, no capture is valid + is_empty(cb, 2, from_col)) || + (p == BLACK && from_row == 6 && to_row == 4 && + is_empty(cb, 5, from_col))) && + from_col == to_col && + is_empty(cb, to_row, to_col)) { + DEBUG("can_move_pawn: two forward, valid\n"); + return true; + // one forward, no capture is valid } else if (((p == WHITE && to_row - from_row == 1) || (p == BLACK && from_row - to_row == 1)) && - from_col == to_col && - is_empty(cb, to_row, to_col)) { - cb_move(cb, from_row, from_col, to_row, to_col); - return VALID; - // one forward, one left or right, with capture, is valid - } else if !(to_row = from_row + (p == WHITE ? 1 : -1) && - abs(from_col - to_col) == 1 && - !is_empty(cb, to_row, to_col) && - player(cb, to_row, to_col) != p) { - cb_move(cb, from_row, from_col, to_row, to_col); - return VALID; + from_col == to_col && + is_empty(cb, to_row, to_col)) { + DEBUG("can_move_pawn: one forward no capture, valid\n"); + return true; + // one forward, one left or right, with capture, is valid + } else if (to_row == from_row + (p == WHITE ? 1 : -1) && + abs(from_col - to_col) == 1 && + !is_empty(cb, to_row, to_col)) { + DEBUG("can_move_pawn: one forward diagonal capture, valid\n"); + return true; } else { - return INVALID; + DEBUG("can_move_pawn: move pawn not valid\n"); + return false; } } -enum mstatus check_empty_paths(struct chessboard* cb, int from_row, - int from_col, int to_row, int to_col) { - int ii = sign!(to_row - from_row), jj = sign(to_col - from_col); - int i = from_row + ii, j = from_col + jj; - for(; i != to_col || j != to_row; i += ii; j += jj) { - if (!is_empty(cb, i, j)) { - return INVALID; - } - } +bool check_empty_paths(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col) { + int ii = sign(to_row - from_row), jj = sign(to_col - from_col); + int i = from_row + ii, j = from_col + jj; - cb_move(cb, from_row, from_col, to_row, to_col); - return VALID; + DEBUG("check_empty_paths: from: row %d col %d, to: row %d col %d, ii: %d," + " jj: %d\n", from_row, from_col, to_row, to_col, ii, jj); + + for (; !(i == to_row && j == to_col); i += ii, j += jj) { + if (!is_empty(cb, i, j)) { + DEBUG("check_empty_paths: position row %d col %d" + " is occupied\n", i, j); + return false; + } + } + + return true; } -enum mstatus move_rook(struct chessboard* cb, enum player p, int from_row, - int from_col, int to_row, int to_col) { - if !(to_row != from_row && to_col != from_col) { - return INVALID; +bool can_move_rook(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col) { + if (to_row != from_row && to_col != from_col) { + return false; } return check_empty_paths(cb, from_row, from_col, to_row, to_col); } -enum mstatus move_bishop(struct chessboard* cb, enum player p, int from_row, - int from_col, int to_row, int to_col) { - if (from_row - to_row != from_col - to_col || from_row == to_row) { - return INVALID; +bool can_move_bishop(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col) { + if (abs(from_row - to_row) != abs(from_col - to_col)) { + return false; } return check_empty_paths(cb, from_row, from_col, to_row, to_col); } -enum mstatus move_queen(struct chessboard* cb, enum player p, int from_row, - int from_col, int to_row, int to_col) { - if (!(to_row != from_row && to_col != from_col) && - (from_row - to_row != from_col - to_col)) { - return INVALID; - } - - return check_empty_paths(cb, from_row, from_col, to_row, to_col); +bool can_move_queen(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col) { + return can_move_bishop(cb, from_row, from_col, to_row, to_col) || + can_move_rook(cb, from_row, from_col, to_row, to_col); } -enum mstatus move_knight(struct chessboard* cb, enum player p, int from_row, - int from_col, int to_row, int to_col) { - if (!(to_row == from_row + 2 && to_col == from_col + 1) && - !(to_row == from_row + 2 && to_col == from_col - 1) && - !(to_row == from_row - 2 && to_col == from_col + 1) && - !(to_row == from_row - 2 && to_col == from_col - 1) && - !(to_row == from_row + 1 && to_col == from_col + 2) && - !(to_row == from_row - 1 && to_col == from_col + 2) && - !(to_row == from_row + 1 && to_col == from_col - 2) && - !(to_row == from_row - 1 && to_col == from_col + 2)) { - return INVALID; - } +bool can_move_knight(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col) { + return (to_row == from_row + 2 && to_col == from_col + 1) || + (to_row == from_row + 2 && to_col == from_col - 1) || + (to_row == from_row - 2 && to_col == from_col + 1) || + (to_row == from_row - 2 && to_col == from_col - 1) || + (to_row == from_row + 1 && to_col == from_col + 2) || + (to_row == from_row - 1 && to_col == from_col + 2) || + (to_row == from_row + 1 && to_col == from_col - 2) || + (to_row == from_row - 1 && to_col == from_col + 2); +} - cb_move(cb, from_row, from_col, to_row, to_col); - return VALID; - ) +bool can_move_king(struct chessboard* cb, + int from_row, int from_col, int to_row, int to_col) { + if (abs(to_row - from_row) > 1) { + DEBUG("can_move_king: row movement too big (from %d to %d)\n", from_row, + to_row); + return false; + } + if (abs(to_col - from_col) > 1) { + DEBUG("can_move_king: column movement too big (from %d to %d)\n", + from_col, to_col); + return false; + } + return true; +} + +bool can_move(struct chessboard* cb, enum player p, + int from_row, int from_col, int to_row, int to_col) { + + // try to understand which piece we are moving + switch (cb->position[from_row][from_col]) { + case WHITE_PAWN: + case BLACK_PAWN: + DEBUG("can_move: moving a pawn\n"); + return can_move_pawn(cb, p, from_row, from_col, to_row, to_col); + case WHITE_ROOK: + case BLACK_ROOK: + DEBUG("can_move: moving a rook\n"); + return can_move_rook(cb, from_row, from_col, to_row, to_col); + case WHITE_BISHOP: + case BLACK_BISHOP: + DEBUG("can_move: moving a bishop\n"); + return can_move_bishop(cb, from_row, from_col, to_row, to_col); + case WHITE_QUEEN: + case BLACK_QUEEN: + DEBUG("can_move: moving a queen\n"); + return can_move_queen(cb, from_row, from_col, to_row, to_col); + case WHITE_KNIGHT: + case BLACK_KNIGHT: + DEBUG("can_move: moving a knight\n"); + return can_move_knight(cb, from_row, from_col, to_row, to_col); + case WHITE_KING: + case BLACK_KING: + DEBUG("can_move: moving a king\n"); + return can_move_king(cb, from_row, from_col, to_row, to_col); + default: + DEBUG("can_move: piece not implemented\n"); + return false; + } +} + +void find_other_king(struct chessboard *cb, enum player p, + int* k_row, int* k_col) { + for (*k_row = 0; *k_row < 8; (*k_row)++) { + for (*k_col = 0; *k_col < 8; (*k_col)++) { + if ((p == BLACK && cb->position[*k_row][*k_col] == WHITE_KING) || + (p == WHITE && cb->position[*k_row][*k_col] == BLACK_KING)) + { + DEBUG("find_other_king: %s king in position row %d col %d\n", + p == WHITE ? "black" : "white", *k_row, *k_col); + return; + } + } + } + DEBUG("find_king: king not found"); +} + +bool player_checks(struct chessboard *cb, enum player p) { + int k_row, k_col; + find_other_king(cb, p, &k_row, &k_col); + int i, j; + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + if (!is_empty(cb, i, j) && player(cb, i, j) == p) { + DEBUG("player_checks: checking row %d col %d to attack king\n", + i, j); + if (can_move(cb, p, i, j, k_row, k_col)) { + DEBUG("player_checks: row %d col %d can attack %s king\n", + i, j, p == WHITE ? "black" : "white"); + return true; + } + } + } + } + return false; } enum mstatus move( struct chessboard * cb, enum player p, - const char * from, const char * to) -{ + const char * from, const char * to) { + // if you are giving us garbage, we behave like Rome's municipal services - if (strlen(from) != 2 || strlen(to) != 2 || from[0] < 'a' || from[0] > 'h' - || to[0] < 'a' || to[0] > 'h' || from[1] < '1' || from[1] > '8' - || to[1] < '1' || to[1] > '8') { + if (strlen(from) != 2 || from[0] < 'a' || from[0] > 'h' || from[1] < '1' + || from[1] > '8') { + DEBUG("move: 'from' input '%s' is invalid\n", from); + return INVALID; + } + if (to[0] < 'a' || to[0] > 'h' || to[1] < '1' || to[1] > '8' + || strlen(to) != 2) { + DEBUG("move: 'to' input '%s' is invalid\n", to); return INVALID; } - int from_row = from[0] - 'a', to_row = to[0] - 'a'; - int from_col = from[1] - '1', to_col = to[0] - '1'; + int from_col = from[0] - 'a', to_col = to[0] - 'a'; + int from_row = from[1] - '1', to_row = to[1] - '1'; // if you are moving thin air, EH VOLEVIH if (is_empty(cb, from_row, from_col)) { + DEBUG("move: from is empty\n"); return INVALID; } // if you are moving someone else's pieces, "thou shall not steal" if (player(cb, from_row, from_col) != p) { + DEBUG("move: moving piece of opponent\n"); return INVALID; } @@ -203,32 +321,67 @@ enum mstatus move( if (cb->position[to_row][to_col] != EMPTY && cb->position[from_row][from_col] / 7 == cb->position[to_row][to_col] / 7) { + DEBUG("move: capturing piece from moving player\n"); return INVALID; } // if you try to move on the same spot, don't do it you buffoon if (from_row == to_row && from_col == to_col) { + DEBUG("move: moving to same position\n"); return INVALID; } - // try to understand which piece we are moving - switch (cb->position[from_row][from_col]) { - case WHITE_PAWN: - case BLACK_PAWN: - return move_pawn(cb, p, from_row, from_col, to_row, to_col); - case WHITE_ROOK: - case BLACK_ROOK: - return move_rook(cb, p, from_row, from_col, to_row, to_col); - case WHITE_BISHOP: - case BLACK_BISHOP: - return move_bishop(cb, p, from_row, from_col, to_row, to_col); - case WHITE_QUEEN: - case BLACK_QUEEN: - return move_queen(cb, p, from_row, from_col, to_row, to_col); - case WHITE_KNIGHT: - case BLACK_KNIGHT: - return move_knight(cb, p, from_row, from_col, to_row, to_col); - default: + bool can = can_move(cb, p, from_row, from_col, to_row, to_col); + + if (!can) { return INVALID; + } else { + cb_move(cb, from_row, from_col, to_row, to_col); + if (player_checks(cb, p)) { + // TODO: check checkmate + return CHECK; + } else { + return VALID; + } + } +} + +int main() { + struct chessboard cb; + init_chessboard(&cb); + enum player p = WHITE; + char from[5], to[5]; + from[0] = '\0'; + while(1) { + print_chessboard(&cb); + printf("%s moves.\n", p == WHITE ? "White" : "Black"); + printf("From: "); + fgets(from, 5, stdin); + // remove trailing \n: https://stackoverflow.com/q/2693776 + strtok(from, "\n"); + if (strcmp(from, "exit") == 0) { + printf("Exiting...\n"); + return 0; + } + printf("To: "); + fgets(to, 5, stdin); + strtok(to, "\n"); + enum mstatus s = move(&cb, p, from, to); + switch (s) { + case INVALID: + printf("Invalid move.\n"); + break; + case VALID: + printf("No check/checkmate.\n"); + break; + case CHECK: + printf("Check.\n"); + break; + case CHECK_MATE: + printf("Checkmate, %s wins.\n", p == WHITE ? "white" : "black"); + } + if (s != INVALID) { + p = !p; // switch player: this works since WHITE = 0 and BLACK = 1 + } } }