diff options
Diffstat (limited to 'src/engine/moves')
| -rw-r--r-- | src/engine/moves/attack.c | 154 | ||||
| -rw-r--r-- | src/engine/moves/king.c | 47 | ||||
| -rw-r--r-- | src/engine/moves/vec.c | 19 |
3 files changed, 208 insertions, 12 deletions
diff --git a/src/engine/moves/attack.c b/src/engine/moves/attack.c new file mode 100644 index 0000000..e4923ea --- /dev/null +++ b/src/engine/moves/attack.c @@ -0,0 +1,154 @@ +#define MOVES_INTERNAL +#include "engine/moves.h" + +static bool pawn_attacks_square(position_t position, square_t square, u8 by_color) { + bitboard_t enemy_pawns; + if (by_color == WHITE_TURN) { + enemy_pawns = position.bitboards[WHITE_PAWN]; + if (square < 8) return false; + bitboard_t nw = (square % 8 == 7) ? 0 : (enemy_pawns >> (square - 7)); + bitboard_t ne = (square % 8 == 0) ? 0 : (enemy_pawns >> (square - 9)); + return (nw | ne) & 1; + } else { + enemy_pawns = position.bitboards[BLACK_PAWN]; + if (square > 54) return false; + bitboard_t se = (square % 8 == 0) ? 0 : (enemy_pawns >> (square + 7)); + bitboard_t sw = (square % 8 == 7) ? 0 : (enemy_pawns >> (square + 9)); + return (se | sw) & 1; + } +} + +static bool knight_attacks_square(position_t position, square_t square, u8 by_color) { + bitboard_t enemy_knights = (by_color == WHITE_TURN) + ? position.bitboards[WHITE_KNIGHT] + : position.bitboards[BLACK_KNIGHT]; + return knight_moves[square] & enemy_knights; +} + +static bool king_attacks_square(position_t position, square_t square, u8 by_color) { + bitboard_t enemy_king = (by_color == WHITE_TURN) + ? position.bitboards[WHITE_KING] + : position.bitboards[BLACK_KING]; + bitboard_t movement; + if (square >= 10) { + movement = 920078ULL << (square - 10); + } else { + movement = 920078ULL >> -(square - 10); + } + if ((bitboard_t)1 << square & BITMASK_FILE_A) { + movement &= BITMASK_FILE_A | BITMASK_FILE_B; + } else if ((bitboard_t)1 << square & BITMASK_FILE_H) { + movement &= BITMASK_FILE_G | BITMASK_FILE_H; + } + return movement & enemy_king; +} + +static bool sliding_attacks_square( + position_t position, + square_t square, + u8 by_color, + bool check_rook, + bool check_bishop +) { + bitboard_t all_occupied = whites(position) | blacks(position); + int rank = square / 8; + int file = square % 8; + + bitboard_t enemy_rooks = (by_color == WHITE_TURN) ? position.bitboards[WHITE_ROOK] : position.bitboards[BLACK_ROOK]; + bitboard_t enemy_bishops = (by_color == WHITE_TURN) ? position.bitboards[WHITE_BISHOP] : position.bitboards[BLACK_BISHOP]; + bitboard_t enemy_queens = (by_color == WHITE_TURN) ? position.bitboards[WHITE_QUEEN] : position.bitboards[BLACK_QUEEN]; + + if (check_rook) { + bitboard_t rook_like = enemy_rooks | enemy_queens; + + int r, idx; + r = rank + 1; + while (r < 8) { + idx = r * 8 + file; + if ((all_occupied >> idx) & 1) { + if ((rook_like >> idx) & 1) return true; + break; + } + r++; + } + r = rank - 1; + while (r >= 0) { + idx = r * 8 + file; + if ((all_occupied >> idx) & 1) { + if ((rook_like >> idx) & 1) return true; + break; + } + r--; + } + int f = file + 1; + while (f < 8) { + idx = rank * 8 + f; + if ((all_occupied >> idx) & 1) { + if ((rook_like >> idx) & 1) return true; + break; + } + f++; + } + f = file - 1; + while (f >= 0) { + idx = rank * 8 + f; + if ((all_occupied >> idx) & 1) { + if ((rook_like >> idx) & 1) return true; + break; + } + f--; + } + } + + if (check_bishop) { + bitboard_t bishop_like = enemy_bishops | enemy_queens; + + int r, f, idx; + r = rank + 1; f = file + 1; + while (r < 8 && f < 8) { + idx = r * 8 + f; + if ((all_occupied >> idx) & 1) { + if ((bishop_like >> idx) & 1) return true; + break; + } + r++; f++; + } + r = rank - 1; f = file - 1; + while (r >= 0 && f >= 0) { + idx = r * 8 + f; + if ((all_occupied >> idx) & 1) { + if ((bishop_like >> idx) & 1) return true; + break; + } + r--; f--; + } + r = rank - 1; f = file + 1; + while (r >= 0 && f < 8) { + idx = r * 8 + f; + if ((all_occupied >> idx) & 1) { + if ((bishop_like >> idx) & 1) return true; + break; + } + r--; f++; + } + r = rank + 1; f = file - 1; + while (r < 8 && f >= 0) { + idx = r * 8 + f; + if ((all_occupied >> idx) & 1) { + if ((bishop_like >> idx) & 1) return true; + break; + } + r++; f--; + } + } + + return false; +} + +bool square_attacked(position_t position, square_t square, u8 by_color) { + if (pawn_attacks_square(position, square, by_color)) return true; + if (knight_attacks_square(position, square, by_color)) return true; + if (king_attacks_square(position, square, by_color)) return true; + if (sliding_attacks_square(position, square, by_color, true, true)) return true; + return false; +} diff --git a/src/engine/moves/king.c b/src/engine/moves/king.c index 706cf9c..98c6ab9 100644 --- a/src/engine/moves/king.c +++ b/src/engine/moves/king.c @@ -42,15 +42,51 @@ void get_king_moves(moves_t* moves, position_t position) { .flags = ((enemy_pieces >> to) & 1) ? MOVE_CAPTURE : 0, ); } + + bitboard_t all_occupied = friendly_pieces | enemy_pieces; + if (position.turn == WHITE_TURN) { + if ((position.castling & WHITE_SHORT_CASTLE) && + king_square == 4 && + !((all_occupied >> 5) & 1) && + !((all_occupied >> 6) & 1)) + { + add_move(moves, 4, 6, .flags = MOVE_SHORT_CASTLE); + } + if ((position.castling & WHITE_LONG_CASTLE) && + king_square == 4 && + !((all_occupied >> 3) & 1) && + !((all_occupied >> 2) & 1) && + !((all_occupied >> 1) & 1)) + { + add_move(moves, 4, 2, .flags = MOVE_LONG_CASTLE); + } + } else { + if ((position.castling & BLACK_SHORT_CASTLE) && + king_square == 60 && + !((all_occupied >> 61) & 1) && + !((all_occupied >> 62) & 1)) + { + add_move(moves, 60, 62, .flags = MOVE_SHORT_CASTLE); + } + if ((position.castling & BLACK_LONG_CASTLE) && + king_square == 60 && + !((all_occupied >> 59) & 1) && + !((all_occupied >> 58) & 1) && + !((all_occupied >> 57) & 1)) + { + add_move(moves, 60, 58, .flags = MOVE_LONG_CASTLE); + } + } } #ifdef TEST_MOD #include <stdbool.h> -#include "vec.c" bool test_white_king_corners() { - moves_t moves = moves_init(); + moves_t moves; + moves_init(&moves); position_t p = {0}; + p.bitboards[BLACK_KING] = 100; p.bitboards[WHITE_KING] = 1; p.turn = WHITE_TURN; get_king_moves(&moves, p); @@ -82,12 +118,16 @@ bool test_white_king_corners() { if (moves.moves[2].from != 56) return false; if (moves.moves[2].to != 57) return false; + moves_deinit(moves); return true; } bool test_black_king_corners() { - moves_t moves = moves_init(); + moves_t moves; + moves_init(&moves); + position_t p = {0}; + p.bitboards[WHITE_KING] = 100; p.bitboards[BLACK_KING] = 1; p.turn = BLACK_TURN; get_king_moves(&moves, p); @@ -119,6 +159,7 @@ bool test_black_king_corners() { if (moves.moves[2].from != 56) return false; if (moves.moves[2].to != 57) return false; + moves_deinit(moves); return true; } #endif diff --git a/src/engine/moves/vec.c b/src/engine/moves/vec.c index b5cbb6f..6da3eb9 100644 --- a/src/engine/moves/vec.c +++ b/src/engine/moves/vec.c @@ -3,17 +3,18 @@ #include <assert.h> #include <stdlib.h> -moves_t moves_init() { - return moves_init_wcapacity(16); +void moves_init(moves_t *moves) { + return moves_init_wcapacity(moves, 16); } -moves_t moves_init_wcapacity(u32 capacity) { - move_t* moves = malloc(capacity * sizeof(*moves)); - return (moves_t) { - .moves = moves, - .capacity = capacity, - .length = 0, - }; +void moves_deinit(moves_t moves) { + free(moves.moves); +} + +void moves_init_wcapacity(moves_t *moves, u32 capacity) { + moves->moves = malloc(capacity * sizeof(*moves)); + moves->length = 0; + moves->capacity = capacity; } moves_t moves_empty() { |
