From 5c162f413edd1586b47d61d7eb544a2e8b512220 Mon Sep 17 00:00:00 2001 From: Ole Morud Date: Thu, 28 Mar 2024 18:39:32 +0100 Subject: [PATCH] Add castling --- src/chess.c | 357 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 230 insertions(+), 127 deletions(-) diff --git a/src/chess.c b/src/chess.c index eddd34c..b130d8e 100644 --- a/src/chess.c +++ b/src/chess.c @@ -1,13 +1,13 @@ #include -#include /* isalpha, isdigit ... */ -#include /* setlocale */ +#include /* isalpha, isdigit ... */ +#include /* setlocale */ #include #include /* true, false, bool */ #include /* ptrdiff_t */ #include /* int32_t */ -#include /* printf, scanf */ -#include /* memcpy */ +#include /* printf, scanf */ +#include /* memcpy */ #include typedef int32_t piece_t; @@ -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; } - g->board[to] = g->board[from]; - g->board[from] = EMPTY; + 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) { - return BIT(index+1) | BIT(index+ROW+1) | BIT (index+ROW); + // 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 (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 (row(index) == 0 && column(index) == 7) { - return BIT(index-1) | BIT(index+ROW-1) | BIT (index+ROW); + 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) { + 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); + } } - 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) { - return BIT(index-1) | BIT(index+1) | BIT(index+ROW-1) | BIT(index+ROW) | BIT(index+ROW+1); - } - else if (row(index) == 7) { - return BIT(index-1) | BIT(index+1) | BIT(index-ROW-1) | BIT(index-ROW) | BIT(index-ROW+1); - } - 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); - } - 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) - fputc('\n', stdout); - if (threatmap & BIT(i)) - fputc('x', stdout); - else - fputc('-', stdout); + for (ssize_t i=7; i >= 0; i--) { + fputc('\n', stdout); + 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); - score += player * piece_value[type] * piece_position_bonus[type][i]; + 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("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("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("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