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 }