movelist.cpp (5384B)
1 #include "movelist.hpp" 2 #include "piece.hpp" 3 #include <iomanip> 4 5 #define pawn_canPromote(color, source) \ 6 ((color == WHITE && source >= Square::a7 && source <= Square::h7) || \ 7 (color == BLACK && source >= Square::a2 && source <= Square::h2)) 8 9 #define pawn_onStart(color, source) \ 10 ((color == BLACK && source >= Square::a7 && source <= Square::h7) || \ 11 (color == WHITE && source >= Square::a2 && source <= Square::h2)) 12 13 using Type::PAWN; 14 15 void MoveList::generate(const Board &board, bool attacks_only) { 16 uint8_t src_i = 0, tgt_i = 0; 17 18 const Color color = board.get_side(), colorOther = other(color); 19 20 // pawn moves 21 const int add = (color == WHITE) ? +8 : -8; 22 23 U64 bitboard = board.get_bitboard_piece(PAWN, color); 24 bitboard_for_each_bit(src_i, bitboard) { 25 const auto src = static_cast<Square>(src_i); 26 const auto tgt = static_cast<Square>(tgt_i = src_i + add); 27 if (!attacks_only && !board.is_square_occupied(tgt)) { 28 if (pawn_canPromote(color, src)) { 29 list.emplace_back(src, tgt, Move::PKNIGHT); 30 list.emplace_back(src, tgt, Move::PBISHOP); 31 list.emplace_back(src, tgt, Move::PROOK); 32 list.emplace_back(src, tgt, Move::PQUEEN); 33 } else { 34 list.emplace_back(src, tgt, Move::PQUIET); 35 36 // two ahead 37 const auto tgt = static_cast<Square>(tgt_i + add); 38 if (pawn_onStart(color, src) && !board.is_square_occupied(tgt)) 39 list.emplace_back(src, tgt, Move::DOUBLE); 40 } 41 } 42 43 // capture 44 U64 attack = 45 board.get_bitboard_piece_attacks(PAWN, color, src) & board.get_bitboard_color(colorOther); 46 bitboard_for_each_bit(tgt_i, attack) { 47 const auto tgt = static_cast<Square>(tgt_i); 48 if (pawn_canPromote(color, src)) { 49 list.emplace_back(src, tgt, Move::PCKNIGHT); 50 list.emplace_back(src, tgt, Move::PCBISHOP); 51 list.emplace_back(src, tgt, Move::PCROOK); 52 list.emplace_back(src, tgt, Move::PCQUEEN); 53 } else { 54 list.emplace_back(src, tgt, Move::CAPTURE); 55 } 56 } 57 58 // en passant 59 const Square enpassant = board.get_enpassant(); 60 if (enpassant != Square::no_sq && board.is_piece_attack_square(PAWN, color, src, enpassant)) 61 list.emplace_back(src, enpassant, Move::ENPASSANT); 62 } 63 64 // All piece move 65 for (Type type = KNIGHT; type <= KING; ++type) { 66 U64 bitboard = board.get_bitboard_piece(type, color); 67 bitboard_for_each_bit(src_i, bitboard) { 68 const auto src = static_cast<Square>(src_i); 69 U64 attack = board.get_bitboard_piece_moves(type, color, src); 70 bitboard_for_each_bit(tgt_i, attack) { 71 const auto tgt = static_cast<Square>(tgt_i); 72 if (board.is_square_occupied(tgt)) { 73 list.emplace_back(src, tgt, Move::CAPTURE); 74 } else { 75 if (attacks_only) continue; 76 list.emplace_back(src, tgt, Move::QUIET); 77 } 78 } 79 } 80 } 81 82 if (attacks_only) return; 83 84 // Castling 85 if (color == WHITE) { 86 if (!board.is_square_attacked(Square::e1, BLACK)) { 87 if (board.get_castle() & Board::Castle::WK) { 88 if (!board.is_square_occupied(Square::f1) && !board.is_square_occupied(Square::g1) && 89 !board.is_square_attacked(Square::f1, BLACK)) 90 list.emplace_back(Square::e1, Square::g1, Move::CASTLEK); 91 } 92 if (board.get_castle() & Board::Castle::WQ) { 93 if (!board.is_square_occupied(Square::d1) && !board.is_square_occupied(Square::c1) && 94 !board.is_square_occupied(Square::b1) && !board.is_square_attacked(Square::d1, BLACK) && 95 !board.is_square_attacked(Square::c1, BLACK)) 96 list.emplace_back(Square::e1, Square::c1, Move::CASTLEQ); 97 } 98 } 99 } else { 100 if (!board.is_square_attacked(Square::e8, WHITE)) { 101 if (board.get_castle() & Board::Castle::BK) { 102 if (!board.is_square_occupied(Square::f8) && !board.is_square_occupied(Square::g8) && 103 !board.is_square_attacked(Square::f8, WHITE)) 104 list.emplace_back(Square::e8, Square::g8, Move::CASTLEK); 105 } 106 if (board.get_castle() & Board::Castle::BQ) { 107 if (!board.is_square_occupied(Square::d8) && !board.is_square_occupied(Square::c8) && 108 !board.is_square_occupied(Square::b8) && !board.is_square_attacked(Square::d8, WHITE) && 109 !board.is_square_attacked(Square::c8, WHITE)) 110 list.emplace_back(Square::e8, Square::c8, Move::CASTLEQ); 111 } 112 } 113 } 114 } 115 116 std::ostream &operator<<(std::ostream &os, const MoveList &list) { 117 os << "Size: " << std::dec << list.size() << "\n"; 118 for (const Move move : list.list) { 119 os << move << "\n"; 120 } 121 return os; 122 }