Add castling

This commit is contained in:
2024-03-28 18:39:32 +01:00
parent 29e5b3c2bb
commit 5c162f413e

View File

@@ -56,7 +56,7 @@ static const double piece_value[] = {
[KNIGHT] = 3,
[ROOK] = 5,
[QUEEN] = 9,
[KING] = 0,
[KING] = 10,
};
static const double piece_position_bonus[7][BOARD_SIZE * sizeof(double)] = {
@@ -64,10 +64,10 @@ static const double piece_position_bonus[7][BOARD_SIZE * sizeof(double)] = {
[PAWN] = {
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.4, 1.4, 1.4, 1.4, 1.0, 1.0,
1.0, 1.0, 1.4, 1.4, 1.4, 1.4, 1.0, 1.0,
1.2, 1.0, 1.4, 1.4, 1.4, 1.4, 1.0, 1.2,
1.7, 1.0, 1.4, 1.4, 1.4, 1.4, 1.0, 1.7,
1.0, 1.0, 1.4, 1.4, 1.4, 1.4, 1.0, 1.0,
1.0, 1.0, 1.4, 1.4, 1.4, 1.4, 1.0, 1.0,
1.0, 1.0, 1.4, 1.4, 1.4, 1.4, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
},
@@ -85,10 +85,10 @@ static const double piece_position_bonus[7][BOARD_SIZE * sizeof(double)] = {
0.5, 0.7, 0.8, 0.8, 0.8, 0.8, 0.7, 0.5,
0.6, 0.7, 0.9, 0.9, 0.9, 0.9, 0.7, 0.6,
0.6, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.6,
0.6, 1.0, 1.0, 1.1, 1.1, 1.0, 1.0, 0.6,
0.6, 1.0, 1.0, 1.1, 1.1, 1.0, 1.0, 0.6,
0.6, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.6,
0.6, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.6,
0.6, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.6,
0.6, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.6,
0.6, 0.7, 0.9, 0.9, 0.9, 0.9, 0.7, 0.6,
0.5, 0.7, 0.8, 0.8, 0.8, 0.8, 0.7, 0.5,
},
[ROOK] = {
@@ -112,6 +112,8 @@ static const double piece_position_bonus[7][BOARD_SIZE * sizeof(double)] = {
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
},
[KING] = {
/*a b c d e f g h*/
1.4, 1.4, 1.4, 1.0, 1.0, 1.0, 99, 1.6,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
@@ -119,21 +121,13 @@ static const double piece_position_bonus[7][BOARD_SIZE * sizeof(double)] = {
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.001, 1.001, 1.0, 1.0, 1.0, 1.0, 1.001, 1.001,
},
};
#define TILE(col, row) ((col)-'A'+ROW*((row)-1))
//static inline index_t tile(char col, int row)
//{
// assert(row >= 1);
// assert(row <= 8);
// assert(col >= 'A');
// assert(col <= 'H');
// return col-'A' + ROW*(row-1);
//}
static bool friends(piece_t a, piece_t b)
#define TILE(col, row) ((col)-'A'+ ROW*((row)-1))
static inline bool friends(piece_t a, piece_t b)
{
return a * b > 0;
}
@@ -154,26 +148,44 @@ static int signum(int t)
return -1;
}
static index_t row(index_t i)
static inline index_t row(index_t i)
{
return i / ROW;
}
static index_t column(index_t i)
static inline index_t column(index_t i)
{
return i % ROW;
}
static bool enemies(piece_t a, piece_t b)
static inline bool enemies(piece_t a, piece_t b)
{
return a * b < 0;
}
static piece_t piece_color(piece_t t)
static inline piece_t piece_color(piece_t t)
{
return (piece_t)signum(t);
}
static const char * piece_str(piece_t p) {
static const char * const table[] = {
[EMPTY] = "EMPTY",
[PAWN] = "PAWN",
[BISHOP] = "BISHOP",
[KNIGHT] = "KNIGHT",
[ROOK] = "ROOK",
[QUEEN] = "QUEEN",
[KING] = "KING",
};
p = piece_abs(p);
if (p >= 0 && (size_t)p < sizeof table / sizeof *table) {
return table[piece_abs(p)];
} else {
return "UNKNOWN";
}
}
static void board_paint(struct game_state* g)
{
/* https://en.wikipedia.org/wiki/Chess_symbols_in_Unicode
@@ -184,8 +196,9 @@ static void board_paint(struct game_state* g)
#define FG_BLACK() printf("\033[38;2;0;0;0m")
#define FG_WHITE() printf("\033[38;2;255;255;255m")
#define UNICODE_CHESS_SYMBOL 0x2659
for (size_t i = 0; i < 8; i++) {
printf("\n %zu ", 8 - i); // number coordinates
for (ssize_t i = 7; i >= 0; i--) {
//for (ssize_t i = 0; i < 8; i++) {
printf("\n %zu ", i+1); // number coordinates
for (size_t j = 0; j < 8; j++) {
piece_t t = g->board[i * 8 + j];
if ((i + j) % 2)
@@ -218,13 +231,13 @@ static void move(struct game_state* g, index_t from, index_t to)
if (piece_abs(g->board[from]) == KING) {
g->king_pos[p] = to;
g->king_touched[p] = true;
} else if (from == TILE('A', 7)) {
} else if (from == TILE('A', 8)) {
g->a_rook_touched[0] = true;
} else if (from == TILE('A', 0)) {
} else if (from == TILE('A', 1)) {
g->a_rook_touched[1] = true;
} else if (from == TILE('H', 0)) {
} else if (from == TILE('H', 1)) {
g->h_rook_touched[0] = true;
} else if (from == TILE('H', 7)) {
} else if (from == TILE('H', 8)) {
g->h_rook_touched[1] = true;
}
@@ -234,22 +247,57 @@ static void move(struct game_state* g, index_t from, index_t to)
g->turns_without_captures = 0;
}
if (piece_abs(g->board[from]) == KING) {
switch (to) {
case TILE('G', 1):
g->board[TILE('E', 1)] = EMPTY;
g->board[TILE('F', 1)] = ROOK;
g->board[TILE('G', 1)] = KING;
g->board[TILE('H', 1)] = EMPTY;
break;
case TILE('C', 1):
g->board[TILE('A', 1)] = EMPTY;
g->board[TILE('B', 1)] = EMPTY;
g->board[TILE('C', 1)] = KING;
g->board[TILE('D', 1)] = ROOK;
g->board[TILE('E', 1)] = EMPTY;
break;
case TILE('G', 8):
g->board[TILE('E', 8)] = EMPTY;
g->board[TILE('F', 8)] = ROOK;
g->board[TILE('G', 8)] = KING;
g->board[TILE('H', 8)] = EMPTY;
break;
case TILE('C', 8):
g->board[TILE('A', 8)] = EMPTY;
g->board[TILE('B', 8)] = EMPTY;
g->board[TILE('C', 8)] = KING;
g->board[TILE('D', 8)] = ROOK;
g->board[TILE('E', 8)] = EMPTY;
break;
default:
g->board[to] = g->board[from];
g->board[from] = EMPTY;
return;
}
} else {
g->board[to] = g->board[from];
g->board[from] = EMPTY;
}
}
static bitmap_t pawn_threatmap(struct game_state* g, index_t index)
{
index_t direction = -1 * piece_color(g->board[index]);
index_t left = BIT(index + ROW*direction - 1);
index_t right = BIT(index + ROW*direction + 1);
const index_t direction = piece_color(g->board[index]);
const index_t left = BIT(index + ROW*direction - 1);
const index_t right = BIT(index + ROW*direction + 1);
if (column(index) == 7)
return left;
if (column(index) == 0)
if (column(index) == column(TILE('A', 1)))
return right;
if (column(index) == column(TILE('H', 1)))
return left;
return left | right;
}
@@ -345,8 +393,10 @@ static bitmap_t knight_threatmap(index_t index)
for (size_t i = 0; i < N_ELEMS(knight_wheel); i += 2) {
index_t atks = index + knight_wheel[i] + knight_wheel[i+1] * ROW;
if (column(index) + knight_wheel[i] < 0 || column(index) + knight_wheel[i] > 7
|| row(index) + knight_wheel[i+1] < 0 || row(index) + knight_wheel[i+1] > 7)
if (column(index) + knight_wheel[i] < 0
|| column(index) + knight_wheel[i] > 7
|| row(index) + knight_wheel[i+1] < 0
|| row(index) + knight_wheel[i+1] > 7)
continue;
threatened |= BIT(atks);
@@ -357,33 +407,40 @@ static bitmap_t knight_threatmap(index_t index)
static bitmap_t king_threatmap(index_t index)
{
if (row(index) == 0 && column(index) == 0) {
// I fucking hate this function so much
if (row(index) == 0) {
if (column(index) == 0) {
return BIT(index+1) | BIT(index+ROW+1) | BIT (index+ROW);
}
else if (row(index) == 0 && column(index) == 7) {
else if (column(index) == 7) {
return BIT(index-1) | BIT(index+ROW-1) | BIT (index+ROW);
}
else if (row(index) == 7 && column(index) == 0) {
return BIT(index+1) | BIT(index-ROW+1) | BIT (index-ROW);
}
else if (row(index) == 7 && column(index) == 7) {
return BIT(index-1) | BIT(index-ROW-1) | BIT (index-ROW);
}
else if (row(index) == 0) {
else {
return BIT(index-1) | BIT(index+1) | BIT(index+ROW-1) | BIT(index+ROW) | BIT(index+ROW+1);
}
else if (row(index) == 7) {
}
if (row(index) == 7) {
if (column(index) == 0) {
return BIT(index+1) | BIT(index-ROW+1) | BIT (index-ROW);
}
else if (column(index) == 7) {
return BIT(index-1) | BIT(index-ROW-1) | BIT (index-ROW);
}
else {
return BIT(index-1) | BIT(index+1) | BIT(index-ROW-1) | BIT(index-ROW) | BIT(index-ROW+1);
}
else if (column(index) == 0) {
} else {
if (column(index) == 0) {
return BIT(index-ROW) | BIT(index-ROW+1) | BIT(index+1) | BIT(index+ROW+1) | BIT(index+ROW);
}
else if (column(index) == 7) {
return BIT(index-ROW) | BIT(index-ROW-1) | BIT(index-1) | BIT(index+ROW-1) | BIT(index+ROW);
}
} else {
return BIT(index-ROW-1) | BIT(index-ROW) | BIT(index-ROW+1)
| BIT(index-1) | BIT(index+1)
| BIT(index+ROW-1) | BIT(index+ROW) | BIT(index+ROW+1);
}
}
}
static inline bitmap_t queen_threatmap(struct game_state* g, index_t index)
@@ -393,16 +450,17 @@ static inline bitmap_t queen_threatmap(struct game_state* g, index_t index)
static void print_threatmap(bitmap_t threatmap)
{
for (size_t i = 0; i < 64; i++) {
putc(' ', stdout);
if (i % 8 == 0)
for (ssize_t i=7; i >= 0; i--) {
fputc('\n', stdout);
if (threatmap & BIT(i))
for (size_t j = 0; j < 8; j++) {
fputc(' ', stdout);
if (threatmap & BIT(i*ROW+j))
fputc('x', stdout);
else
fputc('-', stdout);
}
}
fputc('\n', stdout);
}
static bitmap_t piece_threatmap(struct game_state* g, index_t index)
@@ -430,7 +488,6 @@ static bitmap_t piece_threatmap(struct game_state* g, index_t index)
static bitmap_t threatmap(struct game_state* g, int attacker)
{
bitmap_t threatened = 0;
for(index_t i = 0; i < BOARD_SIZE; i++) {
if (friends(g->board[i], attacker)) {
threatened |= piece_threatmap(g, i);
@@ -442,33 +499,53 @@ static bitmap_t threatmap(struct game_state* g, int attacker)
static bool pawn_move_ok(struct game_state* g, index_t from, index_t to)
{
const index_t direction = -1 * piece_color(g->board[from]);
const index_t direction = piece_color(g->board[from]);
const index_t diff = (to - from) * direction;
//printf("\n");
switch (diff) {
case ROW: /* single move */
//if (!(g->board[to] == EMPTY)) {
// printf("pawn must move to empty tile, ");
//}
return g->board[to] == EMPTY;
case ROW - COL: /* diagonal attack */
case ROW + COL:
//if (!(enemies(g->board[to], g->board[from]))) {
// printf("pawn can't take its own pieces, ");
//}
return enemies(g->board[to], g->board[from]);
case 2 * ROW: /* double move */
//if (!( g->board[to] == EMPTY)) {
// printf("pawn must move to empty piece, ");
//}
//if (!( g->board[from + ROW * direction] == EMPTY)) {
// printf("pawn can't jump over piece, ");
//}
//if (!( (row(from) == 1 || row(from) == 6))) {
// printf("pawn can only move two steps from its starting row, ");
//}
//printf("\n");
return g->board[to] == EMPTY
&& g->board[from + ROW * direction] == EMPTY
&& (row(from) == 1 || row(from) == 6);
default: /* any other move is illegal */
//printf("pawn move is generally illegal, ");
return false;
}
}
static bool king_move_ok(struct game_state* g, index_t from, index_t to)
{
// castling is implemented as a separate function, invoked by O-O or O-O-O
// castling check is implemented as a separate function
return BIT(to) & king_threatmap(from)
&& BIT(to) & ~threatmap(g, -piece_color(g->board[from]));
}
bool is_check(struct game_state* g, int player)
{
return BIT(g->king_pos[player == WHITE ? 0 : 1]) & threatmap(g, -player);
@@ -480,15 +557,21 @@ static bool castle_ok(struct game_state* g, int player, enum castle_type t)
return false;
}
const int p = player == WHITE ? 0 : 1;
const int row = ROW * (player == WHITE ? 7 : 0);
const int row = (player == WHITE ? 1 : 8);
if (t == CASTLE_KINGSIDE) {
return g->h_rook_touched[p] == false
&& g->king_touched[p] == false
&& threatmap(g, -player) & (BIT(TILE('F', row)) | BIT(TILE('G', row)));
&& ~threatmap(g, -player) & (BIT(TILE('F', row)) | BIT(TILE('G', row)))
&& g->board[TILE('G', row)] == EMPTY
&& g->board[TILE('F', row)] == EMPTY;
} else if (t == CASTLE_QUEENSIDE) {
return g->a_rook_touched[p] == false
&& g->king_touched[p] == false
&& threatmap(g, -player) & (BIT(TILE('C', row)) | BIT(TILE('D', row)));
&& ~threatmap(g, -player) & (BIT(TILE('C', row)) | BIT(TILE('D', row)))
&& g->board[TILE('B', row)] == EMPTY
&& g->board[TILE('C', row)] == EMPTY
&& g->board[TILE('D', row)] == EMPTY;
}
fprintf(stderr, "invalid castle_type passed to %s", __func__);
@@ -500,8 +583,9 @@ bool move_ok(struct game_state* g, index_t from, index_t to, int player)
{
/* Player must own piece it moves
and a player can't capture their own pieces. */
if (enemies(player, g->board[from]) || friends(player, g->board[to]))
if (enemies(player, g->board[from]) || friends(player, g->board[to])) {
return false;
}
bool move_ok = false;;
@@ -530,12 +614,11 @@ bool move_ok(struct game_state* g, index_t from, index_t to, int player)
return false;
}
// pretend move was done and check if king is checked after
unsigned char restore[sizeof *g];
memcpy(restore, g, sizeof *g);
typeof(*g) restore = *g;
move(g, from, to);
bool bad = is_check(g, player);
memcpy(g, restore, sizeof *g);
*g = restore;
//memcpy(g, &restore, sizeof restore);
if (bad) {
return false;
@@ -586,51 +669,49 @@ static void game_init(struct game_state* g)
// clang-format off
#if 1
static const piece_t start[BOARD_SIZE] = {
-ROOK, -KNIGHT,-BISHOP,-QUEEN, -KING, -BISHOP,-KNIGHT,-ROOK,
-PAWN, -PAWN, -PAWN, -PAWN, -PAWN, -PAWN, -PAWN, -PAWN,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK,
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN,
ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
-PAWN, -PAWN, -PAWN, -PAWN, -PAWN, -PAWN, -PAWN, -PAWN,
-ROOK, -KNIGHT,-BISHOP,-QUEEN, -KING, -BISHOP,-KNIGHT,-ROOK,
};
// clang-format on
#else
static const piece_t start[BOARD_SIZE] = {
-ROOK, -KNIGHT,-BISHOP,-QUEEN, -KING, -BISHOP,-KNIGHT,-ROOK,
-PAWN, -PAWN, -PAWN, -PAWN, -PAWN, QUEEN, -PAWN, -PAWN,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, ROOK, EMPTY, EMPTY,
ROOK, EMPTY, EMPTY, EMPTY, KING, EMPTY, EMPTY, ROOK,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN,
ROOK, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, ROOK
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, -KING, EMPTY, EMPTY, EMPTY,
};
#endif
memset(g, 0, sizeof *g);
memcpy(g->board, start, sizeof start);
g->king_pos[0] = 60;
g->king_pos[1] = 4;
g->king_pos[0] = TILE('E', 1);
g->king_pos[1] = TILE('E', 8);
}
static index_t input_to_index(char input[2])
{
const char col = toupper(input[0]);
const char row = toupper(input[1]);
const char row = input[1];
if (col < 'A' || col > 'H' || row < '1' || row > '8')
return -1;
const int x = col - 'A';
const int y = row - '1';
return 8 * (7 - y) + x;
return TILE(col, row - '0');
}
// TODO: Implement algebaric notation
static int do_turn(int turn_no, struct game_state* g)
static int player_move(int turn_no, struct game_state* g)
{
char input[3] = { 0 };
@@ -645,7 +726,7 @@ static int do_turn(int turn_no, struct game_state* g)
if (from == -1)
return 0;
print_threatmap(valid_moves(g, g->king_pos[turn_no % 2], turn_no % 2 ? BLACK : WHITE));
print_threatmap(valid_moves(g, from, turn_no % 2 ? BLACK : WHITE));
printf("\nto: ");
scanf(" %2s", input);
@@ -675,7 +756,11 @@ static double heuristic(struct game_state* g, int player)
const piece_t piece = g->board[i];
const int player = piece_color(piece);
const piece_t type = piece_abs(piece);
if (player == WHITE) {
score += player * piece_value[type] * piece_position_bonus[type][i];
} else {
score += player * piece_value[type] * piece_position_bonus[type][BOARD_SIZE-i-1];
}
}
return score;
}
@@ -689,15 +774,22 @@ static void print_debug(struct game_state* g, int player)
// bool h_rook_touched[2];
// bool king_touched[2];
//};
static const char * const bool_str[2] = {"False", "True"};
printf("White A king touched: %s\n", bool_str[g->king_touched[0]]);
printf("White A rook touched: %s\n", bool_str[g->a_rook_touched[0]]);
printf("White H rook touched: %s\n", bool_str[g->h_rook_touched[0]]);
printf("White can king side castle: %s\n", bool_str[castle_ok(g, WHITE, CASTLE_KINGSIDE)]);
printf("White can queen side castle: %s\n", bool_str[castle_ok(g, WHITE, CASTLE_QUEENSIDE)]);
printf("White king pos: %c%ld\n", 'A'+((char)column(g->king_pos[0])), 1+row(g->king_pos[0]));
//printf("Black A king touched: %s\n", bool_str[g->king_touched[1]]);
//printf("Black A rook touched: %s\n", bool_str[g->a_rook_touched[1]]);
//printf("Black H rook touched: %s\n", bool_str[g->h_rook_touched[1]]);
//printf("Black can king side castle: %s\n", bool_str[castle_ok(g, BLACK, CASTLE_KINGSIDE)]);
//printf("Black can queen side castle: %s\n", bool_str[castle_ok(g, BLACK, CASTLE_QUEENSIDE)]);
//printf("Black king pos: %c%ld\n", 'A'+((char)column(g->king_pos[1])), 1+row(g->king_pos[1]));
printf("White king pos: %c%ld\n", 'A'+((char)column(g->king_pos[0])), 8-row(g->king_pos[0]));
printf("Black king pos: %c%ld\n", 'A'+((char)column(g->king_pos[1])), 8-row(g->king_pos[1]));
printf("White A king touched: %s\n", g->king_touched[0] ? "True" : "False");
printf("Black A king touched: %s\n", g->king_touched[1] ? "True" : "False");
printf("White A rook touched: %s\n", g->a_rook_touched[0] ? "True" : "False");
printf("Black A rook touched: %s\n", g->a_rook_touched[1] ? "True" : "False");
printf("White H rook touched: %s\n", g->h_rook_touched[0] ? "True" : "False");
printf("Black H rook touched: %s\n", g->h_rook_touched[1] ? "True" : "False");
printf("Turns with no capture: %d\n", g->turns_without_captures);
printf("Estimated score: %lf\n", heuristic(g, player));
}
@@ -774,8 +866,19 @@ int main()
game_init(&state);
#if 0
board_paint(&state);
print_debug(&state, WHITE);
printf("white threatmap:\n");
print_threatmap(threatmap(&state, WHITE));
printf("black threatmap:\n");
print_threatmap(threatmap(&state, BLACK));
}
#else
int turn = 0;
int player = WHITE;
bool player_intervention = false;
while (true) {
print_debug(&state, player);
@@ -784,15 +887,15 @@ int main()
if (is_check(&state, player)) {
printf("%s in check!\n", player == WHITE ? "White" : "Black");
//print_threatmap(piece_threatmap(&state, state.king_pos[player == WHITE ? 0 : 1]));
print_threatmap(piece_threatmap(&state, state.king_pos[player == WHITE ? 0 : 1]));
}
bool player_intervention = false;
if (player_intervention) {
intervene:
while (do_turn(turn, &state) == 0)
/*noop*/;
intervene:
while (player_move(turn, &state) == 0) {
printf("Valid moves for %s:\n", player == WHITE ? "white" : "black");
print_threatmap(valid_moves(&state, state.king_pos[player == WHITE ? 0 : 1], player));
}
} else {
printf("thinking...\n");
index_t from = -1, to = -1;
@@ -801,13 +904,13 @@ intervene:
printf("computer couldn't think, starting player intervention\n");
printf("Valid moves for %s:\n", player == WHITE ? "white" : "black");
print_threatmap(valid_moves(&state, state.king_pos[player == WHITE ? 0 : 1], player));
printf("\nThreatened pieces\n");
printf("\nThreatened pieces by %s\n", -player == WHITE ? "white" : "black");
print_threatmap(threatmap(&state, -player));
player_intervention = true;
goto intervene;
}
move(&state, from, to);
printf("Did %c%ld to %c%ld\n", (char)('A'+column(from)), 8-row(from), (char)('A'+column(to)), 8-row(to));
printf("Did %c%ld to %c%ld\n", (char)('A'+column(from)), 1+row(from), (char)('A'+column(to)), 1+row(to));
}
turn += 1;
@@ -831,4 +934,4 @@ intervene:
return EXIT_SUCCESS;
}
#endif