Files
chessc/src/chess.h
T

190 lines
5.1 KiB
C

#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 <stdbool.h>
// 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