2019-08-04 15:27:01 +00:00
|
|
|
// vim: set ts=4 sw=4 et tw=80:
|
|
|
|
|
2019-08-04 13:56:15 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "./chessboard.h"
|
2019-08-04 15:27:01 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdlib.h>
|
2019-08-04 13:56:15 +00:00
|
|
|
|
|
|
|
void init_chessboard(struct chessboard * cb) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
cb->position[1][i] = WHITE_PAWN;
|
|
|
|
cb->position[6][i] = BLACK_PAWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb->position[0][0] = WHITE_ROOK;
|
|
|
|
cb->position[0][1] = WHITE_KNIGHT;
|
|
|
|
cb->position[0][2] = WHITE_BISHOP;
|
|
|
|
cb->position[0][3] = WHITE_QUEEN;
|
|
|
|
cb->position[0][4] = WHITE_KING;
|
|
|
|
cb->position[0][5] = WHITE_BISHOP;
|
|
|
|
cb->position[0][6] = WHITE_KNIGHT;
|
|
|
|
cb->position[0][7] = WHITE_ROOK;
|
|
|
|
|
|
|
|
cb->position[7][0] = BLACK_ROOK;
|
|
|
|
cb->position[7][1] = BLACK_KNIGHT;
|
|
|
|
cb->position[7][2] = BLACK_BISHOP;
|
|
|
|
cb->position[7][3] = BLACK_QUEEN;
|
|
|
|
cb->position[7][4] = BLACK_KING;
|
|
|
|
cb->position[7][5] = BLACK_BISHOP;
|
|
|
|
cb->position[7][6] = BLACK_KNIGHT;
|
|
|
|
cb->position[7][7] = BLACK_ROOK;
|
|
|
|
|
|
|
|
int j;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
for (j = 2; j < 6; j++) {
|
|
|
|
cb->position[j][i] = EMPTY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_chessboard(struct chessboard * cb) {
|
|
|
|
printf(" a b c d e f g h\n"
|
2019-08-04 15:27:01 +00:00
|
|
|
" ┌───┬───┬───┬───┬───┬───┬───┬───┐\n");
|
2019-08-04 13:56:15 +00:00
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 7; i >= 0; i--) {
|
|
|
|
|
|
|
|
printf("%d │", i + 1);
|
|
|
|
|
|
|
|
int j;
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
printf(" %s │", utf_8_pieces[cb->position[i][j]]);
|
|
|
|
}
|
|
|
|
putchar('\n');
|
|
|
|
|
|
|
|
if (i != 0) {
|
|
|
|
printf(" ├───┼───┼───┼───┼───┼───┼───┼───┤\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" └───┴───┴───┴───┴───┴───┴───┴───┘\n"
|
2019-08-04 15:27:01 +00:00
|
|
|
" a b c d e f g h\n");
|
|
|
|
|
|
|
|
}
|
2019-08-04 13:56:15 +00:00
|
|
|
|
2019-08-04 15:27:01 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool is_empty(struct chessboard* cb, int row, int col) {
|
|
|
|
return cb->position[row][col] == EMPTY;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline enum player player(struct chessboard* cb, int row, int col) {
|
|
|
|
return cb->position[row][col] < 7 ? WHITE : BLACK;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum mstatus move_pawn(struct chessboard* cb, enum player p, int from_row,
|
|
|
|
int from_col, int to_row, int 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
|
|
|
|
} 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;
|
|
|
|
} else {
|
|
|
|
return INVALID;
|
|
|
|
}
|
2019-08-04 13:56:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
enum mstatus move(
|
2019-08-04 15:27:01 +00:00
|
|
|
struct chessboard * cb, enum player p,
|
|
|
|
const char * from, const char * to)
|
2019-08-04 13:56:15 +00:00
|
|
|
{
|
2019-08-04 15:27:01 +00:00
|
|
|
// 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') {
|
|
|
|
return INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
int from_row = from[0] - 'a', to_row = to[0] - 'a';
|
|
|
|
int from_col = from[1] - '1', to_col = to[0] - '1';
|
|
|
|
|
|
|
|
// if you are moving thin air, EH VOLEVIH
|
|
|
|
if (cb->position[from_row][from_col] == EMPTY) {
|
|
|
|
return INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if you are moving someone else's pieces, "thou shall not steal"
|
|
|
|
if (cb->position[from_row][from_col] / 7 != p) {
|
|
|
|
return INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if you are trying to suicide (capture your piecies), sorry but assisted
|
|
|
|
// suicide is not legal in italy
|
|
|
|
if (cb->position[to_row][to_col] != EMPTY &&
|
|
|
|
cb->position[from_row][from_col] / 7 ==
|
|
|
|
cb->position[to_row][to_col] / 7) {
|
|
|
|
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);
|
|
|
|
default:
|
|
|
|
return INVALID;
|
|
|
|
}
|
2019-08-04 13:56:15 +00:00
|
|
|
}
|
2019-08-04 15:27:01 +00:00
|
|
|
|