clang-format chess.c

This commit is contained in:
Ole Morud
2023-03-19 21:18:54 +01:00
parent c25b983674
commit 4e4a28b910

189
chess.c
View File

@@ -1,26 +1,26 @@
#include <ctype.h> /* isalpha, isdigit ... */ #include <ctype.h> /* isalpha, isdigit ... */
#include <locale.h> /* setlocale */ #include <locale.h> /* setlocale */
#include <string.h> /* memcpy */
#include <stdio.h> /* printf, scanf */
#include <stdint.h> /* int32_t */
#include <stdbool.h> /* true, false */ #include <stdbool.h> /* true, false */
#include <stdint.h> /* int32_t */
#include <stdio.h> /* printf, scanf */
#include <string.h> /* memcpy */
typedef int32_t tile_t; typedef int32_t tile_t;
typedef ssize_t pos_t; typedef ssize_t pos_t;
#define ROW ( (pos_t) 8 ) #define ROW ((pos_t)8)
#define COL ( (pos_t) 1 ) #define COL ((pos_t)1)
#define BOARD_SIZE ( 8*8*sizeof(tile_t) ) #define BOARD_SIZE (8 * 8 * sizeof(tile_t))
#define E ( (tile_t) 0 ) /* empty */ #define E ((tile_t)0) /* empty */
#define K ( (tile_t) 1 ) /* king */ #define K ((tile_t)1) /* king */
#define Q ( (tile_t) 2 ) /* queen */ #define Q ((tile_t)2) /* queen */
#define R ( (tile_t) 3 ) /* rook */ #define R ((tile_t)3) /* rook */
#define B ( (tile_t) 4 ) /* bishop */ #define B ((tile_t)4) /* bishop */
#define N ( (tile_t) 5 ) /* knight */ #define N ((tile_t)5) /* knight */
#define P ( (tile_t) 6 ) /* pawn */ #define P ((tile_t)6) /* pawn */
#define BG_DARKBLUE() setcolor(0, 100, 100, 150) #define BG_DARKBLUE() setcolor(0, 100, 100, 150)
#define BG_LIGHTBLUE() setcolor(0, 150, 150, 200) #define BG_LIGHTBLUE() setcolor(0, 150, 150, 200)
@@ -32,36 +32,37 @@ typedef ssize_t pos_t;
#define UNICODE_CHESS_SYMBOL 0x2659 #define UNICODE_CHESS_SYMBOL 0x2659
bool bishop_move_ok(tile_t const* board, pos_t from, pos_t to); bool bishop_move_ok(const tile_t *board, pos_t from, pos_t to);
bool cardinal_move_ok(tile_t const *board, pos_t from, pos_t to); bool cardinal_move_ok(const tile_t *board, pos_t from, pos_t to);
bool diagonal_move_ok(tile_t const *board, pos_t from, pos_t to); bool diagonal_move_ok(const tile_t *board, pos_t from, pos_t to);
bool king_move_ok(tile_t const *board, pos_t from, pos_t to); bool king_move_ok(const tile_t *board, pos_t from, pos_t to);
bool knight_move_ok(pos_t from, pos_t to); bool knight_move_ok(pos_t from, pos_t to);
bool move_ok(tile_t* board, pos_t from, pos_t to, int player); bool move_ok(tile_t *board, pos_t from, pos_t to, int player);
bool pawn_move_ok(tile_t const* board, pos_t from, pos_t to, int direction); bool pawn_move_ok(const tile_t *board, pos_t from, pos_t to, int direction);
bool queen_move_ok(tile_t const *board, pos_t from, pos_t to); bool queen_move_ok(const tile_t *board, pos_t from, pos_t to);
bool rook_move_ok(tile_t const *board, pos_t from, pos_t to); bool rook_move_ok(const tile_t *board, pos_t from, pos_t to);
bool tile_empty(tile_t t); bool tile_empty(tile_t t);
int get_piece(char* input); int get_piece(char *input);
pos_t abs_pos(pos_t p); pos_t abs_pos(pos_t p);
pos_t column(pos_t t); pos_t column(pos_t t);
pos_t row(pos_t t); pos_t row(pos_t t);
tile_t abs_tile(tile_t t); tile_t abs_tile(tile_t t);
void do_turn(int turn_no, tile_t *board); void do_turn(int turn_no, tile_t *board);
void init_board(tile_t* board); void init_board(tile_t *board);
void print_board(tile_t* board); void print_board(tile_t *board);
void setcolor(int mode, int r, int g, int b); void setcolor(int mode, int r, int g, int b);
int main(){ int main()
{
int turn = 0; int turn = 0;
setlocale(LC_ALL, "C.UTF-8"); setlocale(LC_ALL, "C.UTF-8");
tile_t board[8*8] = { 0 }; tile_t board[8 * 8] = { 0 };
init_board(board); init_board(board);
while(1) { while (1) {
print_board(board); print_board(board);
do_turn(turn++, board); do_turn(turn++, board);
} }
@@ -76,28 +77,30 @@ int main(){
1: change foreground 1: change foreground
2: reset colors 2: reset colors
*/ */
void setcolor(const int mode, const int r, const int g, const int b){ void setcolor(const int mode, const int r, const int g, const int b)
if( mode == 2 ) {
if (mode == 2)
printf("\033[0m"); printf("\033[0m");
else else
printf("\033[%i;2;%i;%i;%im", mode?38:48, r, g, b); printf("\033[%i;2;%i;%i;%im", mode ? 38 : 48, r, g, b);
}; };
/* Prints the board */ /* Prints the board */
void print_board(tile_t* board){ void print_board(tile_t *board)
{
/* https://en.wikipedia.org/wiki/Chess_symbols_in_Unicode /* https://en.wikipedia.org/wiki/Chess_symbols_in_Unicode
The unicode symbol is calculated from adding 0x2653 with the The unicode symbol is calculated from adding 0x2653 with the
piece value. */ piece value. */
for (size_t i=0; i<8; i++) { for (size_t i = 0; i < 8; i++) {
printf("\n %zu ", 8-i); // print number coordinates on y-axis printf("\n %zu ", 8 - i); // print number coordinates on y-axis
for (size_t j=0; j<8; j++) { for (size_t j = 0; j < 8; j++) {
tile_t p = board[i*8+j]; tile_t p = board[i * 8 + j];
// Make tile dark and light // Make tile dark and light
if ((i+j) % 2) if ((i + j) % 2)
BG_DARKBLUE(); BG_DARKBLUE();
else else
BG_LIGHTBLUE(); BG_LIGHTBLUE();
@@ -123,44 +126,34 @@ void print_board(tile_t* board){
// Print horizontal letter coordinates // Print horizontal letter coordinates
printf("\n "); printf("\n ");
for(int i=0; i<8; i++) for (int i = 0; i < 8; i++)
printf(" %c", 'a'+i); printf(" %c", 'a' + i);
} }
/* /*
* Resets/inits the board * Resets/inits the board
*/ */
void init_board(tile_t *board) void init_board(tile_t *board)
{ {
// black pieces are prefixed by a minus (-) // black pieces are prefixed by a minus (-)
const tile_t start[] = { const tile_t start[]
-R,-N,-B,-Q,-K,-B,-N,-R, = { -R, -N, -B, -Q, -K, -B, -N, -R, -P, -P, -P, -P, -P, -P, -P, -P,
-P,-P,-P,-P,-P,-P,-P,-P, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E,
E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E,
E, E, E, E, E, E, E, E, P, P, P, P, P, P, P, P, R, N, B, Q, K, B, N, R };
E, E, E, E, E, E, E, E,
E, E, E, E, E, E, E, E,
P, P, P, P, P, P, P, P,
R, N, B, Q, K, B, N, R
};
memcpy(board, start, sizeof(start)); memcpy(board, start, sizeof(start));
} }
// TODO: Implement algebaric notation // TODO: Implement algebaric notation
/* Get move, check move and log move for turn <turn_no> */ /* Get move, check move and log move for turn <turn_no> */
void do_turn(int turn_no, tile_t *board) void do_turn(int turn_no, tile_t *board)
{ {
char input[3] = { 0 }; char input[3] = { 0 };
int from = -1, int from = -1, to = -1, tmp;
to = -1,
tmp;
printf("\nPlayer %i, your turn to move", 1 + turn_no%2); printf("\nPlayer %i, your turn to move", 1 + turn_no % 2);
/* temporary and ugly solution - read from and to */ /* temporary and ugly solution - read from and to */
while (from == -1 || to == -1) { while (from == -1 || to == -1) {
@@ -186,7 +179,7 @@ void do_turn(int turn_no, tile_t *board)
to = tmp; to = tmp;
if (!move_ok(board, from, to, turn_no % 2 ? BLACK : WHITE )) { if (! move_ok(board, from, to, turn_no % 2 ? BLACK : WHITE)) {
from = -1; from = -1;
continue; continue;
} }
@@ -196,35 +189,32 @@ void do_turn(int turn_no, tile_t *board)
board[from] = E; board[from] = E;
} }
/* Translates A1, 3B etc. to the 1D index of the board */ /* Translates A1, 3B etc. to the 1D index of the board */
int get_piece(char *input) int get_piece(char *input)
{ {
int x = -1, int x = -1, y = -1, c;
y = -1,
c;
for (int i=0; i<2; i++) { for (int i = 0; i < 2; i++) {
c = input[i]; c = input[i];
if (isalpha(c)) if (isalpha(c))
c = toupper(input[0]); c = toupper(input[0]);
if( 'A' <= c && c <= 'H' ) if ('A' <= c && c <= 'H')
x = c - 'A'; x = c - 'A';
else if('1' <= c && c <= '8') else if ('1' <= c && c <= '8')
y = c - '1'; y = c - '1';
} }
if (x != -1 && y != -1) if (x != -1 && y != -1)
return 8*(7-y) + x; return 8 * (7 - y) + x;
else else
return -1; return -1;
} }
pos_t abs_pos(pos_t p) pos_t abs_pos(pos_t p)
{ {
if(p < 0) if (p < 0)
return -1 * p; return -1 * p;
return p; return p;
@@ -232,7 +222,7 @@ pos_t abs_pos(pos_t p)
tile_t abs_tile(tile_t t) tile_t abs_tile(tile_t t)
{ {
if(t < 0) if (t < 0)
return -1 * t; return -1 * t;
return t; return t;
@@ -259,17 +249,17 @@ pos_t column(pos_t t)
/* Returns true if a and b are tiles of opposite player */ /* Returns true if a and b are tiles of opposite player */
bool opposite_color(tile_t a, tile_t b) bool opposite_color(tile_t a, tile_t b)
{ {
return a*b < 0; return a * b < 0;
} }
/* Returns true if a and b are pieces of the same color */ /* Returns true if a and b are pieces of the same color */
bool same_color(tile_t a, tile_t b) bool same_color(tile_t a, tile_t b)
{ {
return a*b > 0; return a * b > 0;
} }
/* Returns true if a move is valid, false otherwise */ /* Returns true if a move is valid, false otherwise */
bool move_ok(tile_t* board, pos_t from, pos_t to, int const player) bool move_ok(tile_t *board, pos_t from, pos_t to, const int player)
{ {
/* player must own piece it moves */ /* player must own piece it moves */
if (board[from] * player < 0) { if (board[from] * player < 0) {
@@ -285,7 +275,6 @@ bool move_ok(tile_t* board, pos_t from, pos_t to, int const player)
/* check piece specific moves */ /* check piece specific moves */
switch (abs_tile(board[from])) { switch (abs_tile(board[from])) {
/* PAWNS */ /* PAWNS */
case P: case P:
return pawn_move_ok(board, from, to, player); return pawn_move_ok(board, from, to, player);
@@ -317,9 +306,9 @@ bool move_ok(tile_t* board, pos_t from, pos_t to, int const player)
from - index of board piece starts at from - index of board piece starts at
to - index of board piece wants to move to to - index of board piece wants to move to
direction - pawns movement direction */ direction - pawns movement direction */
bool pawn_move_ok(tile_t const* board, pos_t from, pos_t to, int direction) bool pawn_move_ok(const tile_t *board, pos_t from, pos_t to, int direction)
{ {
pos_t const diff = (to - from) * -direction; const pos_t diff = (to - from) * -direction;
switch (diff) { switch (diff) {
default: default:
@@ -328,13 +317,14 @@ bool pawn_move_ok(tile_t const* board, pos_t from, pos_t to, int direction)
case ROW: /* single move */ case ROW: /* single move */
return tile_empty(board[to]); return tile_empty(board[to]);
case ROW - 1: case ROW+1: /* diagonal attack */ case ROW - 1:
case ROW + 1: /* diagonal attack */
return opposite_color(board[to], board[from]); return opposite_color(board[to], board[from]);
case 2 * ROW: /* double move */ case 2 * ROW: /* double move */
return tile_empty(board[to]) return tile_empty(board[to])
&& tile_empty(board[from - ROW * direction]) && tile_empty(board[from - ROW * direction])
&& (row(from) == 1 || row(from) == 6 ); && (row(from) == 1 || row(from) == 6);
} }
} }
@@ -342,22 +332,22 @@ bool pawn_move_ok(tile_t const* board, pos_t from, pos_t to, int direction)
board - array of tiles representing chess board state board - array of tiles representing chess board state
from - index of board piece is at from - index of board piece is at
to - index of board piece tries to move to */ to - index of board piece tries to move to */
bool diagonal_move_ok(tile_t const *board, pos_t from, pos_t to) bool diagonal_move_ok(const tile_t *board, pos_t from, pos_t to)
{ {
pos_t const col_diff = column(to) - column(from); const pos_t col_diff = column(to) - column(from);
pos_t const row_diff = row(to) - row(from); const pos_t row_diff = row(to) - row(from);
pos_t const x_step = col_diff / abs_pos(col_diff); const pos_t x_step = col_diff / abs_pos(col_diff);
pos_t const y_step = ROW * row_diff / abs_pos(row_diff); const pos_t y_step = ROW * row_diff / abs_pos(row_diff);
pos_t const step = x_step + y_step; const pos_t step = x_step + y_step;
if ( abs_pos(col_diff) != abs_pos(row_diff) ) { if (abs_pos(col_diff) != abs_pos(row_diff)) {
printf("\nnot a diagonal move"); printf("\nnot a diagonal move");
return false; return false;
} }
for (pos_t p = from + step; p != to; p += step) { for (pos_t p = from + step; p != to; p += step) {
if (!tile_empty(board[p])) { if (! tile_empty(board[p])) {
printf("\ncan't jump over pieces"); printf("\ncan't jump over pieces");
return false; return false;
} }
@@ -370,25 +360,23 @@ bool diagonal_move_ok(tile_t const *board, pos_t from, pos_t to)
board - array of tiles representing chess board state board - array of tiles representing chess board state
from - index of board piece is at from - index of board piece is at
to - index of board piece tries to move to */ to - index of board piece tries to move to */
bool cardinal_move_ok(tile_t const *board, pos_t from, pos_t to) bool cardinal_move_ok(const tile_t *board, pos_t from, pos_t to)
{ {
pos_t const col_diff = column(to) - column(from); const pos_t col_diff = column(to) - column(from);
pos_t const row_diff = row(to) - row(from); const pos_t row_diff = row(to) - row(from);
if (row_diff > 0 && col_diff > 0) { if (row_diff > 0 && col_diff > 0)
printf("Must move in a straight line"); printf("Must move in a straight line");
}
pos_t step; pos_t step;
if (row_diff) { if (row_diff)
step = ROW * row_diff / abs_pos(row_diff); step = ROW * row_diff / abs_pos(row_diff);
} else { else
step = col_diff / abs_pos(col_diff); step = col_diff / abs_pos(col_diff);
}
for (pos_t p = from + step; p != to; p += step) { for (pos_t p = from + step; p != to; p += step) {
if (!tile_empty(board[p])) { if (! tile_empty(board[p])) {
printf("\ncan't jump over pieces"); printf("\ncan't jump over pieces");
return false; return false;
} }
@@ -401,7 +389,7 @@ bool cardinal_move_ok(tile_t const *board, pos_t from, pos_t to)
board - array of tiles representing chess board state board - array of tiles representing chess board state
from - index of board bishop is at from - index of board bishop is at
to - index of board bishop wants to move to */ to - index of board bishop wants to move to */
bool bishop_move_ok(tile_t const* board, pos_t from, pos_t to) bool bishop_move_ok(const tile_t *board, pos_t from, pos_t to)
{ {
return diagonal_move_ok(board, from, to); return diagonal_move_ok(board, from, to);
} }
@@ -410,7 +398,7 @@ bool bishop_move_ok(tile_t const* board, pos_t from, pos_t to)
board - array of tiles representing chess board state board - array of tiles representing chess board state
from - index of board rook is at from - index of board rook is at
to - index of board rook wants to move to */ to - index of board rook wants to move to */
bool rook_move_ok(tile_t const *board, pos_t from, pos_t to) bool rook_move_ok(const tile_t *board, pos_t from, pos_t to)
{ {
return cardinal_move_ok(board, from, to); return cardinal_move_ok(board, from, to);
} }
@@ -421,8 +409,8 @@ bool rook_move_ok(tile_t const *board, pos_t from, pos_t to)
to - index of board knight wants to move to */ to - index of board knight wants to move to */
bool knight_move_ok(pos_t from, pos_t to) bool knight_move_ok(pos_t from, pos_t to)
{ {
pos_t const abs_col_diff = abs_pos(column(to) - column(from)); const pos_t abs_col_diff = abs_pos(column(to) - column(from));
pos_t const abs_row_diff = abs_pos(row(to) - row(from)); const pos_t abs_row_diff = abs_pos(row(to) - row(from));
return (abs_col_diff == 1 && abs_row_diff == 2) return (abs_col_diff == 1 && abs_row_diff == 2)
|| (abs_col_diff == 2 && abs_row_diff == 1); || (abs_col_diff == 2 && abs_row_diff == 1);
@@ -432,22 +420,21 @@ bool knight_move_ok(pos_t from, pos_t to)
board - array of tiles representing chess board state board - array of tiles representing chess board state
from - index of board king is at from - index of board king is at
to - index of board king wants to move to */ to - index of board king wants to move to */
bool king_move_ok(tile_t const *board, pos_t from, pos_t to) bool king_move_ok(const tile_t *board, pos_t from, pos_t to)
{ {
pos_t const abs_col_diff = abs_pos(column(to) - column(from)); const pos_t abs_col_diff = abs_pos(column(to) - column(from));
pos_t const abs_row_diff = abs_pos(row(to) - row(from)); const pos_t abs_row_diff = abs_pos(row(to) - row(from));
(void)board; (void)board;
return abs_col_diff <= 1 return abs_col_diff <= 1 && abs_row_diff <= 1;
&& abs_row_diff <= 1;
} }
/* Returns true if move is a valid queen move /* Returns true if move is a valid queen move
board - array of tiles representing chess board state board - array of tiles representing chess board state
from - index of board queen is at from - index of board queen is at
to - index of board queen wants to move to */ to - index of board queen wants to move to */
bool queen_move_ok(tile_t const *board, pos_t from, pos_t to) bool queen_move_ok(const tile_t *board, pos_t from, pos_t to)
{ {
return diagonal_move_ok(board, from, to) return diagonal_move_ok(board, from, to)
|| cardinal_move_ok(board, from, to); || cardinal_move_ok(board, from, to);