constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantations
moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
- moveList = generate_moves<KNIGHT, Checks>(pos, moveList, Us, target);
- moveList = generate_moves<BISHOP, Checks>(pos, moveList, Us, target);
- moveList = generate_moves< ROOK, Checks>(pos, moveList, Us, target);
- moveList = generate_moves< QUEEN, Checks>(pos, moveList, Us, target);
-
- if (Type != QUIET_CHECKS && Type != EVASIONS)
+ for (PieceType pt : pos.piece_types())
+ if (pt != PAWN && pt != KING)
+ moveList = generate_moves<Checks>(pos, moveList, Us, pt, target);
+ // generate drops
+ if (pos.piece_drops() && Type != CAPTURES && pos.count_in_hand(Us, ALL_PIECES))
+ for (PieceType pt : pos.piece_types())
+ moveList = generate_drops<Us, Checks>(pos, moveList, pt, target & ~pos.pieces(~Us));
+
+ if (Type != QUIET_CHECKS && Type != EVASIONS && pos.count<KING>(Us))
{
Square ksq = pos.square<KING>(Us);
- Bitboard b = pos.attacks_from<KING>(ksq) & target;
+ Bitboard b = ( (pos.attacks_from(Us, KING, ksq) & pos.pieces())
+ | (pos.moves_from(Us, KING, ksq) & ~pos.pieces())) & target;
while (b)
- *moveList++ = make_move(ksq, pop_lsb(&b));
+ moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, ksq, pop_lsb(&b));
+
+ // Passing move by king
+ if (pos.pass())
+ *moveList++ = make<SPECIAL>(ksq, ksq);
- if (Type != CAPTURES && pos.can_castle(CastlingRights(OO | OOO)))
- {
- if (!pos.castling_impeded(OO) && pos.can_castle(OO))
- moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, ksq, pos.castling_rook_square(OO));
-
- if (!pos.castling_impeded(OOO) && pos.can_castle(OOO))
- moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, ksq, pos.castling_rook_square(OOO));
- }
+ if ((Type != CAPTURES) && pos.can_castle(Us & ANY_CASTLING))
+ for(CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
+ if (!pos.castling_impeded(cr) && pos.can_castle(cr))
- *moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(cr));
++ moveList = make_move_and_gating<CASTLING>(pos, moveList, Us,ksq, pos.castling_rook_square(cr));
+ }
+ // Workaround for passing: Execute a non-move with any piece
+ else if (pos.pass() && !pos.count<KING>(Us) && pos.pieces(Us))
+ *moveList++ = make<SPECIAL>(lsb(pos.pieces(Us)), lsb(pos.pieces(Us)));
+
+ // Castling with non-king piece
- if (!pos.count<KING>(Us) && Type != CAPTURES && pos.can_castle(CastlingRights(OO | OOO)))
++ if (!pos.count<KING>(Us) && Type != CAPTURES && pos.can_castle(Us & ANY_CASTLING))
+ {
+ Square from = make_square(FILE_E, pos.castling_rank(Us));
- if (!pos.castling_impeded(OO) && pos.can_castle(OO))
- moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, from, pos.castling_rook_square(OO));
-
- if (!pos.castling_impeded(OOO) && pos.can_castle(OOO))
- moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, from, pos.castling_rook_square(OOO));
++ for(CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
++ if (!pos.castling_impeded(cr) && pos.can_castle(cr))
++ moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, from, pos.castling_rook_square(cr));
+ }
+
+ // Special moves
+ if (pos.cambodian_moves() && pos.gates(Us))
+ {
+ if (Type != CAPTURES && Type != EVASIONS && (pos.pieces(Us, KING) & pos.gates(Us)))
+ {
+ Square from = pos.square<KING>(Us);
+ Bitboard b = PseudoAttacks[WHITE][KNIGHT][from] & rank_bb(rank_of(from + (Us == WHITE ? NORTH : SOUTH)))
+ & target & ~pos.pieces();
+ while (b)
+ moveList = make_move_and_gating<SPECIAL>(pos, moveList, Us, from, pop_lsb(&b));
+ }
+
+ Bitboard b = pos.pieces(Us, FERS) & pos.gates(Us);
+ while (b)
+ {
+ Square from = pop_lsb(&b);
+ Square to = from + 2 * (Us == WHITE ? NORTH : SOUTH);
+ if (is_ok(to) && (target & to))
+ moveList = make_move_and_gating<SPECIAL>(pos, moveList, Us, from, to);
+ }
}
return moveList;
// Futility pruning: parent node (~5 Elo)
if ( lmrDepth < 6
&& !inCheck
- && ss->staticEval + 235 + 172 * lmrDepth <= alpha
- && (*contHist[0])[movedPiece][to_sq(move)]
- + (*contHist[1])[movedPiece][to_sq(move)]
- + (*contHist[3])[movedPiece][to_sq(move)] < 27400)
+ && !( pos.extinction_value() == -VALUE_MATE
+ && pos.extinction_piece_types().find(ALL_PIECES) == pos.extinction_piece_types().end())
+ && ss->staticEval + (235 + 172 * lmrDepth) * (1 + pos.check_counting()) <= alpha
- && thisThread->mainHistory[us][from_to(move)]
- + (*contHist[0])[history_slot(movedPiece)][to_sq(move)]
++ && (*contHist[0])[history_slot(movedPiece)][to_sq(move)]
+ + (*contHist[1])[history_slot(movedPiece)][to_sq(move)]
- + (*contHist[3])[history_slot(movedPiece)][to_sq(move)] < 25000)
++ + (*contHist[3])[history_slot(movedPiece)][to_sq(move)] < 27400)
continue;
// Prune moves with negative SEE (~20 Elo)
r -= 2 + ttPv;
ss->statScore = thisThread->mainHistory[us][from_to(move)]
- + (*contHist[0])[movedPiece][to_sq(move)]
- + (*contHist[1])[movedPiece][to_sq(move)]
- + (*contHist[3])[movedPiece][to_sq(move)]
+ + (*contHist[0])[history_slot(movedPiece)][to_sq(move)]
+ + (*contHist[1])[history_slot(movedPiece)][to_sq(move)]
+ + (*contHist[3])[history_slot(movedPiece)][to_sq(move)]
- 4926;
- // Reset statScore to zero if negative and most stats shows >= 0
- if ( ss->statScore < 0
- && (*contHist[0])[history_slot(movedPiece)][to_sq(move)] >= 0
- && (*contHist[1])[history_slot(movedPiece)][to_sq(move)] >= 0
- && thisThread->mainHistory[us][from_to(move)] >= 0)
- ss->statScore = 0;
-
// Decrease/increase reduction by comparing opponent's stat score (~10 Elo)
if (ss->statScore >= -102 && (ss-1)->statScore < -114)
r--;