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