int partition(int first, int last) { // move elements satisfying _Pred to beginning of sequence for (; ; ++first) { // find any out-of-order pair for (; first != last && (ms[first].score > 0); ++first) { ; // skip in-place elements at beginning } if (first == last) { break; // done } for (; first != --last && (ms[last].score <= 0);) { ; // skip in-place elements at end } if (first == last) { break; // done } MoveStack temp = ms[last]; ms[last] = ms[first]; ms[first] = temp; } return(first); }
private static void generate_castle( int Side, bool Checks, Position pos, MoveStack[] ms, ref int mpos, int us) { if (pos.castle_impeded(us, Side) || (pos.can_castle_CR(Utils.make_castle_right(us, Side)) == 0)) { return; } // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. var kfrom = pos.king_square(us); var rfrom = pos.castle_rook_square(us, Side); var kto = Utils.relative_square(us, Side == CastlingSideC.KING_SIDE ? SquareC.SQ_G1 : SquareC.SQ_C1); var enemies = pos.pieces_C(us ^ 1); Debug.Assert(!pos.in_check()); int K = pos.chess960 ? kto > kfrom ? -1 : 1 : Side == CastlingSideC.KING_SIDE ? -1 : 1; for (Square s = kto; s != kfrom; s += (Square)K) { if ((pos.attackers_to(s) & enemies) != 0) { return; } } // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. if (pos.chess960 && ((pos.attackers_to(kto, Utils.xor_bit(pos.occupied_squares, rfrom)) & enemies) != 0)) { return; } var m = Utils.make(kfrom, rfrom, MoveTypeC.CASTLING); if (Checks) { var ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); var givesCheck = pos.move_gives_check(m, ci); CheckInfoBroker.Free(); if (!givesCheck) { return; } } ms[mpos++].move = m; }
int pick_best() { int first = curMovePos; int max = curMovePos; if (first != lastMovePos) { for (; ++first != lastMovePos;) { if (ms[max].score < ms[first].score) { max = first; } } } MoveStack temp = ms[curMovePos]; ms[curMovePos] = ms[max]; ms[max] = temp; return(curMovePos); }
private static void generate_castle(CastlingSide Side, bool OnlyChecks, Position pos, MoveStack[] ms, ref int mpos, Color us) { if (pos.castle_impeded(us, Side) || (pos.can_castle_CR(Utils.make_castle_right(us, Side))==0) ) return; // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. Square kfrom = pos.king_square(us); Square rfrom = pos.castle_rook_square(us, Side); Square kto = Utils.relative_square(us, Side == CastlingSideC.KING_SIDE ? SquareC.SQ_G1 : SquareC.SQ_C1); Bitboard enemies = pos.pieces_C(us ^ 1); Debug.Assert(!pos.in_check()); for (Square s = Math.Min(kfrom, kto), e = Math.Max(kfrom, kto); s <= e; s++) if (s != kfrom // We are not in check && ((pos.attackers_to(s) & enemies) != 0)) return; // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. if (pos.chess960 && ((pos.attackers_to(kto, Utils.xor_bit(pos.occupied_squares, rfrom)) & enemies) != 0)) return; Move m = Utils.make_castle(kfrom, rfrom); if (OnlyChecks) { CheckInfo ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); bool givesCheck = pos.move_gives_check(m, ci); CheckInfoBroker.Free(); if (!givesCheck) return; } ms[mpos++].move = m; }
internal static void generate_quiet_check(Position pos, MoveStack[] ms, ref int mpos) { /// generate<MV_NON_CAPTURE_CHECK> generates all pseudo-legal non-captures and knight /// underpromotions that give check. Returns a pointer to the end of the move list. Debug.Assert(!pos.in_check()); var ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); var target = ~pos.occupied_squares; var dc = ci.dcCandidates; while (dc != 0) { var from = Utils.pop_lsb(ref dc); var pt = Utils.type_of(pos.piece_on(from)); if (pt == PieceTypeC.PAWN) { continue; // Will be generated together with direct checks } var b = pos.attacks_from_PTS(pt, from) & ~pos.occupied_squares; if (pt == PieceTypeC.KING) { b &= ~Utils.PseudoAttacks[PieceTypeC.QUEEN][ci.ksq]; } while (b != 0) { ms[mpos++].move = Utils.make_move(from, Utils.pop_lsb(ref b)); } } generate_all(GenType.QUIET_CHECKS, pos, ms, ref mpos, pos.sideToMove, target, ci); CheckInfoBroker.Free(); }
internal static void generate_quiet(Position pos, MoveStack[] ms, ref int mpos) { Debug.Assert(!pos.in_check()); var us = pos.sideToMove; var target = ~pos.occupied_squares; generate_all(GenType.QUIETS, pos, ms, ref mpos, us, target, null); }
internal static void generate_legal(Position pos, MoveStack[] ms, ref int mpos) { /// generate<LEGAL> generates all the legal moves in the given position var pinned = pos.pinned_pieces(); Square ksq = pos.king_square(pos.sideToMove); if (pos.in_check()) { generate_evasion(pos, ms, ref mpos); } else { generate_non_evasion(pos, ms, ref mpos); } var last = mpos; var cur = 0; while (cur != last) { var curMove = ms[cur].move; //if (!pos.pl_move_is_legal(ms[cur].move, pinned)) if ((pinned != 0 || Utils.from_sq(curMove) == ksq || Utils.type_of_move(curMove) == MoveTypeC.ENPASSANT) && !pos.pl_move_is_legal(curMove, pinned)) { ms[cur].move = ms[--last].move; } else { cur++; } } mpos = last; }
internal static void generate_evasion(Position pos, MoveStack[] ms, ref int mpos) { /// generate<EVASIONS> generates all pseudo-legal check evasions when the side /// to move is in check. Returns a pointer to the end of the move list. Debug.Assert(pos.in_check()); ulong b; int from, checksq; var checkersCnt = 0; var us = pos.sideToMove; var ksq = pos.king_square(us); ulong sliderAttacks = 0; var checkers = pos.st.checkersBB; Debug.Assert(checkers != 0); // Find squares attacked by slider checkers, we will remove them from the king // evasions so to skip known illegal moves avoiding useless legality check later. b = checkers; do { checkersCnt++; checksq = Utils.pop_lsb(ref b); Debug.Assert(Utils.color_of(pos.piece_on(checksq)) == Utils.flip_C(us)); switch (Utils.type_of(pos.piece_on(checksq))) { case PieceTypeC.BISHOP: sliderAttacks |= Utils.PseudoAttacks[PieceTypeC.BISHOP][checksq]; break; case PieceTypeC.ROOK: sliderAttacks |= Utils.PseudoAttacks[PieceTypeC.ROOK][checksq]; break; case PieceTypeC.QUEEN: // If queen and king are far or not on a diagonal line we can safely // remove all the squares attacked in the other direction becuase are // not reachable by the king anyway. if ((Utils.between_bb(ksq, checksq) != 0) || ((Utils.bit_is_set(Utils.PseudoAttacks[PieceTypeC.BISHOP][checksq], ksq)) == 0)) { sliderAttacks |= Utils.PseudoAttacks[PieceTypeC.QUEEN][checksq]; } // Otherwise we need to use real rook attacks to check if king is safe // to move in the other direction. For example: king in B2, queen in A1 // a knight in B1, and we can safely move to C1. else { sliderAttacks |= Utils.PseudoAttacks[PieceTypeC.BISHOP][checksq] | pos.attacks_from_ROOK(checksq); } break; default: break; } } while (b != 0); // Generate evasions for king, capture and non capture moves b = Position.attacks_from_KING(ksq) & ~pos.pieces_C(us) & ~sliderAttacks; from = ksq; while (b != 0) { ms[mpos++].move = Utils.make_move(from, Utils.pop_lsb(ref b)); } // Generate evasions for other pieces only if not under a double check if (checkersCnt > 1) { return; } // Blocking evasions or captures of the checking piece var target = Utils.between_bb(checksq, ksq) | checkers; generate_all(GenType.EVASIONS, pos, ms, ref mpos, us, target, null); }
private static void generate_all( GenType type, Position pos, MoveStack[] mlist, ref int mpos, int us, ulong target, CheckInfo ci) { var Checks = type == GenType.QUIET_CHECKS; generate_pawn_moves(us, type, pos, mlist, ref mpos, target, ci); generate_moves(PieceTypeC.KNIGHT, Checks, pos, mlist, ref mpos, us, target, ci); generate_moves(PieceTypeC.BISHOP, Checks, pos, mlist, ref mpos, us, target, ci); generate_moves(PieceTypeC.ROOK, Checks, pos, mlist, ref mpos, us, target, ci); generate_moves(PieceTypeC.QUEEN, Checks, pos, mlist, ref mpos, us, target, ci); if (!Checks && type != GenType.EVASIONS) { Square from = pos.king_square(us); Bitboard b = Position.attacks_from_KING(from) & target; // SERIALIZE(b); while (b != 0) { #if X64 Bitboard bb = b; b &= (b - 1); mlist[mpos++].move = ((Utils.BSFTable[((bb & (0xffffffffffffffff - bb + 1)) * DeBruijn_64) >> 58]) | (from << 6)); #else mlist[mpos++].move = Utils.make_move(from, Utils.pop_lsb(ref b)); #endif } } if (type != GenType.CAPTURES && type != GenType.EVASIONS && pos.can_castle_C(us) != 0) { generate_castle(CastlingSideC.KING_SIDE, Checks, pos, mlist, ref mpos, us); generate_castle(CastlingSideC.QUEEN_SIDE, Checks, pos, mlist, ref mpos, us); } }
private static void generate_moves( int Pt, bool Checks, Position pos, MoveStack[] mlist, ref int mpos, int us, ulong target, CheckInfo ci) { Debug.Assert(Pt != PieceTypeC.KING && Pt != PieceTypeC.PAWN); var pl = pos.pieceList[us][Pt]; var plPos = 0; for (var from = pl[plPos]; from != SquareC.SQ_NONE; from = pl[++plPos]) { if (Checks) { if ((Pt == PieceTypeC.BISHOP || Pt == PieceTypeC.ROOK || Pt == PieceTypeC.QUEEN) && ((Utils.PseudoAttacks[Pt][from] & (ulong)target & ci.checkSq[Pt]) == 0)) { continue; } if ((ci.dcCandidates != 0) && (Utils.bit_is_set(ci.dcCandidates, from) != 0)) { continue; } } var b = pos.attacks_from_PTS(Pt, from) & (ulong)target; if (Checks) { b &= ci.checkSq[Pt]; } // SERIALIZE(b); while (b != 0) { mlist[mpos++].move = Utils.make_move(from, Utils.pop_lsb(ref b)); } } }
private static void generate_direct_checks(PieceType Pt, Position pos, MoveStack[] ms, ref int mpos, Color us, CheckInfo ci) { Debug.Assert(Pt != PieceTypeC.KING && Pt != PieceTypeC.PAWN); Bitboard b, target; Square[] pl = pos.pieceList[us][Pt]; int plPos = 0; Square from = pl[plPos]; if ((from = pl[plPos]) != SquareC.SQ_NONE) { target = ci.checkSq[Pt] & ~pos.occupied_squares; // Non capture checks only do { if ((Pt == PieceTypeC.BISHOP || Pt == PieceTypeC.ROOK || Pt == PieceTypeC.QUEEN) && ((Utils.PseudoAttacks[Pt][from] & target) == 0)) continue; if ((ci.dcCandidates != 0) && (Utils.bit_is_set(ci.dcCandidates, from) != 0)) continue; b = pos.attacks_from_PTS(Pt, from) & target; while (b != 0) { ms[mpos++].move = Utils.make_move(from, Utils.pop_1st_bit(ref b)); } } while ((from = pl[++plPos]) != SquareC.SQ_NONE); } }
private static void generate_pawn_moves( int Us, GenType Type, Position pos, MoveStack[] ms, ref int mpos, ulong target, CheckInfo ci) { // Compute our parametrized parameters at compile time, named according to // the point of view of white side. var Them = (Us == ColorC.WHITE ? ColorC.BLACK : ColorC.WHITE); var TRank8BB = (Us == ColorC.WHITE ? Constants.Rank8BB : Constants.Rank1BB); var TRank7BB = (Us == ColorC.WHITE ? Constants.Rank7BB : Constants.Rank2BB); var TRank3BB = (Us == ColorC.WHITE ? Constants.Rank3BB : Constants.Rank6BB); var UP = (Us == ColorC.WHITE ? SquareC.DELTA_N : SquareC.DELTA_S); var RIGHT = (Us == ColorC.WHITE ? SquareC.DELTA_NE : SquareC.DELTA_SW); var LEFT = (Us == ColorC.WHITE ? SquareC.DELTA_NW : SquareC.DELTA_SE); ulong b1, b2, dc1, dc2, emptySquares = 0; int to; var pawnsOn7 = (pos.byTypeBB[PieceTypeC.PAWN] & pos.byColorBB[Us]) & TRank7BB; var pawnsNotOn7 = (pos.byTypeBB[PieceTypeC.PAWN] & pos.byColorBB[Us]) & ~TRank7BB; var enemies = (Type == GenType.EVASIONS ? pos.byColorBB[Them] & target : Type == GenType.CAPTURES ? target : pos.byColorBB[Them]); // Single and double pawn pushes, no promotions if (Type != GenType.CAPTURES) { emptySquares = (Type == GenType.QUIETS ? target : ~pos.occupied_squares); b1 = move_pawns(UP, pawnsNotOn7) & emptySquares; b2 = move_pawns(UP, b1 & TRank3BB) & emptySquares; if (Type == GenType.EVASIONS) // Consider only blocking squares { b1 &= target; b2 &= target; } if (Type == GenType.QUIET_CHECKS) { b1 &= Utils.StepAttacksBB[((Them << 3) | PieceTypeC.PAWN)][ci.ksq]; b2 &= Utils.StepAttacksBB[((Them << 3) | PieceTypeC.PAWN)][ci.ksq]; // Add pawn pushes which give discovered check. This is possible only // if the pawn is not on the same file as the enemy king, because we // don't generate captures. Note that a possible discovery check // promotion has been already generated among captures. if ((pawnsNotOn7 & ci.dcCandidates) != 0) // Target is dc bitboard { dc1 = move_pawns(UP, pawnsNotOn7 & ci.dcCandidates) & emptySquares & ~(Utils.FileBB[ci.ksq & 7]); dc2 = move_pawns(UP, dc1 & TRank3BB) & emptySquares; b1 |= dc1; b2 |= dc2; } } while (b1 != 0) { to = Utils.pop_lsb(ref b1); ms[mpos++].move = (to | ((to - UP) << 6)); } while (b2 != 0) { to = Utils.pop_lsb(ref b2); ms[mpos++].move = (to | ((to - UP - UP) << 6)); } } // Promotions and underpromotions if ((pawnsOn7 != 0) && (Type != GenType.EVASIONS || ((target & TRank8BB) != 0))) { if (Type == GenType.CAPTURES) { emptySquares = ~pos.occupied_squares; } if (Type == GenType.EVASIONS) { emptySquares &= target; } generate_promotions(Type, RIGHT, ms, ref mpos, pawnsOn7, enemies, ci); generate_promotions(Type, LEFT, ms, ref mpos, pawnsOn7, enemies, ci); generate_promotions(Type, UP, ms, ref mpos, pawnsOn7, emptySquares, ci); } // Standard and en-passant captures if (Type == GenType.CAPTURES || Type == GenType.EVASIONS || Type == GenType.NON_EVASIONS) { b1 = move_pawns(RIGHT, pawnsNotOn7) & enemies; b2 = move_pawns(LEFT, pawnsNotOn7) & enemies; while (b1 != 0) { to = Utils.pop_lsb(ref b1); ms[mpos++].move = (to | ((to - RIGHT) << 6)); } while (b2 != 0) { to = Utils.pop_lsb(ref b2); ms[mpos++].move = (to | ((to - LEFT) << 6)); } if (pos.st.epSquare != SquareC.SQ_NONE) { Debug.Assert(Utils.rank_of(pos.st.epSquare) == Utils.relative_rank_CR(Us, RankC.RANK_6)); // An en passant capture can be an evasion only if the checking piece // is the double pushed pawn and so is in the target. Otherwise this // is a discovery check and we are forced to do otherwise. if (Type == GenType.EVASIONS && (((target & Utils.SquareBB[pos.st.epSquare - UP]) == 0))) { return; } b1 = pawnsNotOn7 & Utils.StepAttacksBB[((Them << 3) | PieceTypeC.PAWN)][pos.st.epSquare]; Debug.Assert(b1 != 0); while (b1 != 0) { ms[mpos++].move = Utils.make(Utils.pop_lsb(ref b1), pos.st.epSquare, MoveTypeC.ENPASSANT); } } } }
internal static void generate_non_evasion(Position pos, MoveStack[] ms, ref int mpos) { Debug.Assert(!pos.in_check()); var us = pos.sideToMove; var target = ~(pos.byColorBB[us]); generate_all(GenType.NON_EVASIONS, pos, ms, ref mpos, us, target, null); }
private static void generate_king_moves(Position pos, MoveStack[] ms, ref int mpos, Color us, Bitboard target) { Square from = pos.pieceList[us][PieceTypeC.KING][0]; Bitboard b = Utils.StepAttacksBB_KING[from] & target; while (b != 0) { #if X64 Bitboard bb = b; b &= (b - 1); ms[mpos++].move = ((Utils.BSFTable[((bb & (0xffffffffffffffff - bb + 1)) * 0x218A392CD3D5DBFUL) >> 58]) | (from << 6)); #else ms[mpos++].move = Utils.make_move(from, Utils.pop_1st_bit(ref b)); #endif } }
internal static void generate_capture(Position pos, MoveStack[] ms, ref int mpos) { Debug.Assert(!pos.in_check()); Color us = pos.sideToMove; Bitboard target = pos.byColorBB[us ^ 1]; generate_pawn_moves(us, MoveType.MV_CAPTURE, pos, ms, ref mpos, target, SquareC.SQ_NONE); generate_moves(pos, ms, ref mpos, us, target); generate_king_moves(pos, ms, ref mpos, us, target); }
internal static void generate_non_evasion(Position pos, MoveStack[] ms, ref int mpos) { Debug.Assert(!pos.in_check()); Color us = pos.sideToMove; Bitboard target = ~(pos.byColorBB[us]); generate_pawn_moves(us, MoveType.MV_NON_EVASION, pos, ms, ref mpos, target, SquareC.SQ_NONE); generate_moves(pos, ms, ref mpos, us, target); generate_king_moves(pos, ms, ref mpos, us, target); if ((pos.st.castleRights & (CastleRightC.WHITE_ANY << (us << 1))) != 0) { generate_castle(CastlingSideC.KING_SIDE, false, pos, ms, ref mpos, us); generate_castle(CastlingSideC.QUEEN_SIDE, false, pos, ms, ref mpos, us); } }
internal static void generate_quiet_check(Position pos, MoveStack[] ms, ref int mpos) { /// generate<MV_NON_CAPTURE_CHECK> generates all pseudo-legal non-captures and knight /// underpromotions that give check. Returns a pointer to the end of the move list. Debug.Assert(!pos.in_check()); Color us = pos.sideToMove; CheckInfo ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); Bitboard dc = ci.dcCandidates; while (dc != 0) { Square from = Utils.pop_1st_bit(ref dc); PieceType pt = Utils.type_of(pos.piece_on(from)); if (pt == PieceTypeC.PAWN) continue; // Will be generated together with direct checks Bitboard b = pos.attacks_from_PTS(pt, from) & ~pos.occupied_squares; if (pt == PieceTypeC.KING) b &= ~Utils.PseudoAttacks[PieceTypeC.QUEEN][ci.ksq]; while (b != 0) { ms[mpos++].move = Utils.make_move(from, Utils.pop_1st_bit(ref b)); } } generate_pawn_moves(us, MoveType.MV_QUIET_CHECK, pos, ms, ref mpos, ci.dcCandidates, ci.ksq); generate_direct_checks(PieceTypeC.KNIGHT, pos, ms, ref mpos, us, ci); generate_direct_checks(PieceTypeC.BISHOP, pos, ms, ref mpos, us, ci); generate_direct_checks(PieceTypeC.ROOK, pos, ms, ref mpos, us, ci); generate_direct_checks(PieceTypeC.QUEEN, pos, ms, ref mpos, us, ci); if (pos.can_castle_C(us) != 0) { generate_castle(CastlingSideC.KING_SIDE, true, pos, ms, ref mpos, us); generate_castle(CastlingSideC.QUEEN_SIDE, true, pos, ms, ref mpos, us); } CheckInfoBroker.Free(); }
internal static void generate_legal(Position pos, MoveStack[] ms, ref int mpos) { /// generate<MV_LEGAL> generates all the legal moves in the given position Bitboard pinned = pos.pinned_pieces(); if (pos.in_check()) { generate_evasion(pos, ms, ref mpos); } else { generate_non_evasion(pos, ms, ref mpos); } int last = mpos; int cur = 0; while (cur != last) { if (!pos.pl_move_is_legal(ms[cur].move, pinned)) { ms[cur].move = ms[--last].move; } else { cur++; } } mpos = last; }
private static void generate_moves(Position pos, MoveStack[] ms, ref int mpos, Color us, Bitboard target) { Bitboard b; int plPos; for (PieceType pieceType = PieceTypeC.KNIGHT; pieceType < PieceTypeC.KING; pieceType++) { Square[] pl = pos.pieceList[us][pieceType]; Square s = pl[plPos = 0]; if (s != SquareC.SQ_NONE) { do { #if X64 if (pieceType == PieceTypeC.BISHOP) { b = Utils.BAttacks[s][(((pos.occupied_squares & Utils.BMasks[s]) * Utils.BMagics[s]) >> Utils.BShifts[s])] & target; } else if (pieceType == PieceTypeC.ROOK) { b = Utils.RAttacks[s][(((pos.occupied_squares & Utils.RMasks[s]) * Utils.RMagics[s]) >> Utils.RShifts[s])] & target; } else if (pieceType == PieceTypeC.QUEEN) { b = (Utils.BAttacks[s][(((pos.occupied_squares & Utils.BMasks[s]) * Utils.BMagics[s]) >> Utils.BShifts[s])] | Utils.RAttacks[s][(((pos.occupied_squares & Utils.RMasks[s]) * Utils.RMagics[s]) >> Utils.RShifts[s])]) & target; } else b = Utils.StepAttacksBB[pieceType][s] & target; while (b != 0) { Bitboard bb = b; b &= (b - 1); ms[mpos++].move = (Utils.BSFTable[((bb & (0xffffffffffffffff - bb + 1)) * 0x218A392CD3D5DBFUL) >> 58]) | (s << 6); } #else if (pieceType == PieceTypeC.BISHOP) { b = Utils.bishop_attacks_bb(s, pos.occupied_squares) & target; ; } else if (pieceType == PieceTypeC.ROOK) { b = Utils.rook_attacks_bb(s, pos.occupied_squares) & target; ; } else if (pieceType == PieceTypeC.QUEEN) { b = (Utils.bishop_attacks_bb(s, pos.occupied_squares) | Utils.rook_attacks_bb(s, pos.occupied_squares)) & target; } else b = Utils.StepAttacksBB[pieceType][s] & target; while (b != 0) { ms[mpos++].move = Utils.make_move(s, Utils.pop_1st_bit(ref b)); } #endif } while ((s = pl[++plPos]) != SquareC.SQ_NONE); } } }
internal static void generate_capture(Position pos, MoveStack[] ms, ref int mpos) { Debug.Assert(!pos.in_check()); var us = pos.sideToMove; var target = pos.byColorBB[us ^ 1]; generate_all(GenType.CAPTURES, pos, ms, ref mpos, us, target, null); }
private static void generate_promotions(MoveType Type, Square Delta, MoveStack[] ms, ref int mpos, Bitboard pawnsOn7, Bitboard target, Square ksq) { Bitboard b = move_pawns(Delta, pawnsOn7) & target; while (b != 0) { Square to = Utils.pop_1st_bit(ref b); if (Type == MoveType.MV_CAPTURE || Type == MoveType.MV_EVASION || Type == MoveType.MV_NON_EVASION) ms[mpos++].move = Utils.make_promotion(to - Delta, to, PieceTypeC.QUEEN); if (Type == MoveType.MV_QUIET || Type == MoveType.MV_EVASION || Type == MoveType.MV_NON_EVASION) { ms[mpos++].move = Utils.make_promotion(to - Delta, to, PieceTypeC.ROOK); ms[mpos++].move = Utils.make_promotion(to - Delta, to, PieceTypeC.BISHOP); ms[mpos++].move = Utils.make_promotion(to - Delta, to, PieceTypeC.KNIGHT); } // Knight-promotion is the only one that can give a direct check not // already included in the queen-promotion. if (Type == MoveType.MV_QUIET_CHECK && (Utils.bit_is_set(Utils.StepAttacksBB[PieceC.W_KNIGHT][to], ksq) != 0)) ms[mpos++].move = Utils.make_promotion(to - Delta, to, PieceTypeC.KNIGHT); } }
internal static void sort(MoveStack[] data, int firstMove, int lastMove) { MoveStack tmp; int p, q; for (p = firstMove + 1; p < lastMove; p++) { tmp = data[p]; for (q = p; q != firstMove && data[q - 1].score < tmp.score; --q) { data[q] = data[q - 1]; } data[q] = tmp; } }
private static void generate_promotions( GenType Type, int Delta, MoveStack[] ms, ref int mpos, ulong pawnsOn7, ulong target, CheckInfo ci) { var b = move_pawns(Delta, pawnsOn7) & target; while (b != 0) { var to = Utils.pop_lsb(ref b); if (Type == GenType.CAPTURES || Type == GenType.EVASIONS || Type == GenType.NON_EVASIONS) { ms[mpos++].move = Utils.make(to - Delta, to, MoveTypeC.PROMOTION, PieceTypeC.QUEEN); } if (Type == GenType.QUIETS || Type == GenType.EVASIONS || Type == GenType.NON_EVASIONS) { ms[mpos++].move = Utils.make(to - Delta, to, MoveTypeC.PROMOTION, PieceTypeC.ROOK); ms[mpos++].move = Utils.make(to - Delta, to, MoveTypeC.PROMOTION, PieceTypeC.BISHOP); ms[mpos++].move = Utils.make(to - Delta, to, MoveTypeC.PROMOTION, PieceTypeC.KNIGHT); } // Knight-promotion is the only one that can give a direct check not // already included in the queen-promotion. if (Type == GenType.QUIET_CHECKS && (Utils.bit_is_set(Utils.StepAttacksBB[PieceC.W_KNIGHT][to], ci.ksq) != 0)) { ms[mpos++].move = Utils.make(to - Delta, to, MoveTypeC.PROMOTION, PieceTypeC.KNIGHT); } } }