#ifndef CHESS_H #define CHESS_H /* the "board" is the playable area on which * pieces move. pieces are represented by numbers: * 0 - no piece * 1 - pawn * 2 - rook * 3 - knight * 4 - bishop * 5 - queen * 6 - king */ #include // board size constraints #define BOARD_HORIZONTAL 8 #define BOARD_VERTICAL 8 // type abstractions typedef enum { WHITE, BLACK } player_e; typedef int board_t[BOARD_VERTICAL][BOARD_HORIZONTAL]; #define PIECE_COUNT 13 // how many unique pieces are there #define MAX_PIECE_MOVE_COUNT 27 // the max possible num of options where to move in one moment typedef enum { NONE, WPAWN, WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, BPAWN, BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING } piece_e; typedef struct { int x; int y; } pos_t; typedef struct { // what // where from // where to piece_e piece; pos_t from; pos_t to; } move_t; // the default arrangment of pieces on the board // negative numbers are black, positive ones white #define BOARD_DEFAULT_CONFIG \ (board_t){\ { BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK },\ { BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN },\ { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE },\ { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE },\ { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE },\ { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE },\ { WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN },\ { WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK }\ } typedef struct { piece_e piece; pos_t options[MAX_PIECE_MOVE_COUNT]; unsigned int piece_move_count; } valid_move_t; /** FIXED: ALSO DEPENDS ON THE STATE OF THE GAME - * e.g. a pawn cannot move two places in the middle * of the game but can in the first round * => ASSUME NO OTHER PIECES - then ALWAYS CHECK * FOR PIECE COLLISIONS and FOR ROUND COUNT * (pawn 1 || 2 move) */ /** MAYBE: consider the POV from both sides???!!! */ /** * the NONE, PAWN, KNIGHT and KING pieces' relative_moves are * treated like specific coordinates relative to their * position, * whereas the BISHOP, ROOK and QUEEN pieces' 'moves' * are treated as *directions* in which they can move rather than * absolute x,y values -> e.g. the rook can move * up, down, left, right * n -> and then bounds & edge cases are checked */ #define DEFAULT_VALID_MOVES (valid_move_t[PIECE_COUNT]){\ {NONE, {}, 0},\ \ {WPAWN, {\ { 0, -1}, {-1, -1}, {+1, -1}, { 0, -2}\ }, 4},\ {WROOK, {\ { 0, -1}, { 0, +1}, {-1, 0}, {+1, 0}\ }, 4},\ {WKNIGHT, {\ {-1, -2}, {+1, -2}, {-2, -1}, {-2, +1},\ {+2, -1}, {+2, +1}, {-1, -2}, {-1, +2}\ }, 8},\ {WBISHOP, {\ {-1, -1}, {-1, +1}, {+1, -1}, {+1, +1}\ }, 4},\ {WQUEEN, {\ {0, -1}, {0, +1}, {-1, 0}, {+1, 0},\ {-1, -1}, {-1, +1}, {+1, -1}, {+1, +1}\ }, 8},\ {WKING, {\ { 0, -1}, { 0, +1}, {-1, 0}, {+1, 0},\ {-1, -1}, {-1, +1}, {+1, -1}, {+1, +1}\ }, 8},\ \ {BPAWN, {\ { 0, -1}, {-1, -1}, {+1, -1}, { 0, -2}\ }, 4},\ {BROOK, {\ { 0, -1}, { 0, +1}, {-1, 0}, {+1, 0}\ }, 4},\ {BKNIGHT, {\ {-1, -2}, {+1, -2}, {-2, -1}, {-2, +1},\ {+2, -1}, {+2, +1}, {-1, -2}, {-1, +2}\ }, 8},\ {BBISHOP, {\ {-1, -1}, {-1, +1}, {+1, -1}, {+1, +1}\ }, 4},\ {BQUEEN, {\ {0, -1}, {0, +1}, {-1, 0}, {+1, 0},\ {-1, -1}, {-1, +1}, {+1, -1}, {+1, +1}\ }, 8},\ {BKING, {\ { 0, -1}, { 0, +1}, {-1, 0}, {+1, 0},\ {-1, -1}, {-1, +1}, {+1, -1}, {+1, +1}\ }, 8}\ } /** * states in which the game can end * CONTINUE => the game does not end, it continues * CHECKMATE => one side wins * STALEMATE => it's a draw */ typedef enum { CONTINUE, CHECKMATE, STALEMATE } end_condition_e; /** * a tracker for which pieces have been captured by who * white contains opponent pieces WHITE have been captured by them * black contains opponent pieces BLACK have been captured by them */ #define PIECE_COUNT_CAPTURABLE_PER_PLAYER 15 // 2*8 - 1 typedef struct { piece_e white[PIECE_COUNT_CAPTURABLE_PER_PLAYER]; unsigned int white_n; piece_e black[PIECE_COUNT_CAPTURABLE_PER_PLAYER]; unsigned int black_n; } captured_t; // initializes the board with the default configuration of pieces void init_board(board_t *board); // selects the player to currently play // if it is the first round, it selects white void select_player(player_e *player, unsigned int round_count); // listens for a command to make a move by the currently playing player bool get_move(move_t *move); // performs the move if is it possible end_condition_e perform_move(board_t *board, player_e player, captured_t *captured, move_t move); // if there is one of the mates, end the game and show who has won void announce_results(end_condition_e end_condition, player_e player); // shows a guide to help players understand the move prompt system void show_help(); #endif // CHESS_H