stellar

Stellar - Chess engine written in C
Log | Files | Refs

moves_generate.c (5485B)


      1 #include "board.h"
      2 #include "moves.h"
      3 
      4 #define pawn_canPromote(color, source)                                         \
      5     ((color == WHITE && source >= a7 && source <= h7) ||                       \
      6      (color == BLACK && source >= a2 && source <= h2))
      7 
      8 #define pawn_onStart(color, source)                                            \
      9     ((color == BLACK && source >= a7 && source <= h7) ||                       \
     10      (color == WHITE && source >= a2 && source <= h2))
     11 
     12 #define pawn_promote(source, target, Piece, Capture)                           \
     13     for (int i = 1; i < 5; i++) {                                              \
     14         move = move_encode(source, target, Piece, Capture,                     \
     15                            piece_get(i, color), 0, 0, 0);                      \
     16         move_list_add(moves, move);                                            \
     17     }
     18 
     19 MoveList *move_list_generate(MoveList *moves, const Board *board) {
     20     Move move;
     21     Square src, tgt;
     22     eColor color = board_side(board);
     23 
     24     if (!moves)
     25         moves = move_list_new();
     26     else
     27         move_list_reset(moves);
     28 
     29     // pawn moves
     30     Piece piece = piece_get(PAWN, color);
     31     U64 bitboard = board_pieceSet(board, piece);
     32     bitboard_for_each_bit(src, bitboard) {
     33         { // quiet
     34             int add = (color == WHITE) ? +8 : -8;
     35             tgt = src + add;
     36             if (!board_square_isOccupied(board, tgt)) {
     37                 if (pawn_canPromote(color, src)) {
     38                     pawn_promote(src, tgt, piece, 0);
     39                 } else {
     40                     move_list_add(moves,
     41                                   move_encode(src, tgt, piece, 0, 0, 0, 0, 0));
     42 
     43                     // two ahead
     44                     if (pawn_onStart(color, src) &&
     45                         !board_square_isOccupied(board, tgt += add))
     46                         move_list_add(
     47                             moves, move_encode(src, tgt, piece, 0, 0, 1, 0, 0));
     48                 }
     49             }
     50         }
     51         { // capture
     52             U64 attack = board_piece_attacks(board, piece, src) &
     53                          board_color(board, !color);
     54             bitboard_for_each_bit(tgt, attack) {
     55                 if (pawn_canPromote(color, src)) {
     56                     pawn_promote(src, tgt, piece,
     57                                  board_square_piece(board, tgt, !color));
     58                 } else {
     59                     move_list_add(moves, move_encode(src, tgt, piece,
     60                                                      board_square_piece(
     61                                                          board, tgt, !color),
     62                                                      0, 0, 0, 0));
     63                 }
     64             }
     65         }
     66 
     67         { // en passant
     68             if (board_enpassant(board) != no_sq &&
     69                 board_piece_attacks(board, piece, src) &
     70                     (C64(1) << board_enpassant(board)))
     71                 move_list_add(moves,
     72                               move_encode(src, board_enpassant(board), piece,
     73                                           piece_get(PAWN, !color), 0, 0, 1, 0));
     74         }
     75     }
     76 
     77     // All piece move
     78     for (int piece_idx = 1; piece_idx < 6; piece_idx++) {
     79         Piece piece = piece_get(piece_idx, color);
     80         U64 bitboard = board_pieceSet(board, piece);
     81         bitboard_for_each_bit(src, bitboard) {
     82             U64 attack = board_piece_attacks(board, piece, src) &
     83                          ~board_color(board, color);
     84             bitboard_for_each_bit(tgt, attack) {
     85                 move_list_add(
     86                     moves, move_encode(src, tgt, piece,
     87                                        board_square_piece(board, tgt, !color),
     88                                        0, 0, 0, 0));
     89             }
     90         }
     91     }
     92 
     93     // Castling
     94     if (color == WHITE) {
     95         Piece piece = piece_get(KING, WHITE);
     96         if (board_castle(board) & WK) {
     97             if (!board_square_isOccupied(board, f1) &&
     98                 !board_square_isOccupied(board, g1) &&
     99                 !board_square_isAttack(board, e1, BLACK) &&
    100                 !board_square_isAttack(board, f1, BLACK))
    101                 move_list_add(moves, move_encode(e1, g1, piece, 0, 0, 0, 0, 1));
    102         }
    103         if (board_castle(board) & WQ) {
    104             if (!board_square_isOccupied(board, d1) &&
    105                 !board_square_isOccupied(board, c1) &&
    106                 !board_square_isOccupied(board, b1) &&
    107                 !board_square_isAttack(board, e1, BLACK) &&
    108                 !board_square_isAttack(board, d1, BLACK))
    109                 move_list_add(moves, move_encode(e1, c1, piece, 0, 0, 0, 0, 1));
    110         }
    111     } else {
    112         Piece piece = piece_get(KING, BLACK);
    113         if (board_castle(board) & BK) {
    114             if (!board_square_isOccupied(board, f8) &&
    115                 !board_square_isOccupied(board, g8) &&
    116                 !board_square_isAttack(board, e8, WHITE) &&
    117                 !board_square_isAttack(board, f8, WHITE))
    118                 move_list_add(moves, move_encode(e8, g8, piece, 0, 0, 0, 0, 1));
    119         }
    120         if (board_castle(board) & BQ) {
    121             if (!board_square_isOccupied(board, d8) &&
    122                 !board_square_isOccupied(board, c8) &&
    123                 !board_square_isOccupied(board, b8) &&
    124                 !board_square_isAttack(board, e8, WHITE) &&
    125                 !board_square_isAttack(board, d8, WHITE))
    126                 move_list_add(moves, move_encode(e8, c8, piece, 0, 0, 0, 0, 1));
    127         }
    128     }
    129 
    130     return moves;
    131 }